blob: 9ed18e8e228502fee68081c0cee00dce8824af6d [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 Kodihallic4966192018-08-23 02:19:58 -05006#include <fstream>
Deepak Kodihalli4db81462018-08-27 06:01:46 -05007#include <phosphor-logging/elog.hpp>
8#if __has_include("../../usr/include/phosphor-logging/elog-errors.hpp")
9#include "../../usr/include/phosphor-logging/elog-errors.hpp"
10#else
11#include <phosphor-logging/elog-errors.hpp>
12#endif
Deepak Kodihalli4db81462018-08-27 06:01:46 -050013#include <arpa/inet.h>
Patrick Venturef18bf832018-10-26 18:14:00 -070014#include <netdb.h>
Deepak Kodihallic4966192018-08-23 02:19:58 -050015
Lei YUa1c43382021-04-15 20:26:25 +080016#include <optional>
Patrick Venture30047bf2018-11-01 18:52:15 -070017#include <string>
18
Deepak Kodihallic4966192018-08-23 02:19:58 -050019namespace phosphor
20{
21namespace rsyslog_config
22{
23
24namespace utils = phosphor::rsyslog_utils;
Deepak Kodihalli4db81462018-08-27 06:01:46 -050025using namespace phosphor::logging;
26using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Deepak Kodihallic4966192018-08-23 02:19:58 -050027
Lei YUa1c43382021-04-15 20:26:25 +080028namespace internal
29{
30
31bool isIPv6Address(const std::string& addr)
32{
33 struct in6_addr result;
34 return inet_pton(AF_INET6, addr.c_str(), &result) == 1;
35}
36
37std::optional<std::pair<std::string, uint32_t>> parseConfig(std::istream& ss)
38{
39 std::string line;
40 std::getline(ss, line);
41
42 //"*.* @@<address>:<port>" or
43 //"*.* @@[<ipv6-address>:<port>"
44 constexpr auto start = 6; // Skip "*.* @@"
45 std::string serverAddress;
46 std::string serverPort;
47
48 // Ignore if line is commented
49 if (!line.empty() && '#' != line.at(0))
50 {
51 // Check if there is "[]", and make IPv6 address from it
52 auto posColonLeft = line.find('[');
53 auto posColonRight = line.find(']');
54 if (posColonLeft != std::string::npos ||
55 posColonRight != std::string::npos)
56 {
57 // It contains [ or ], so it should be an IPv6 address
58 if (posColonLeft == std::string::npos ||
59 posColonRight == std::string::npos)
60 {
61 // There either '[' or ']', invalid config
62 return {};
63 }
64 if (line.size() < posColonRight + 2 ||
65 line.at(posColonRight + 1) != ':')
66 {
67 // There is no ':', or no more content after ':', invalid config
68 return {};
69 }
70 serverAddress =
71 line.substr(posColonLeft + 1, posColonRight - posColonLeft - 1);
72 serverPort = line.substr(posColonRight + 2);
73 }
74 else
75 {
76 auto pos = line.find(':');
77 if (pos == std::string::npos)
78 {
79 // There is no ':', invalid config
80 return {};
81 }
82 serverAddress = line.substr(start, pos - start);
83 serverPort = line.substr(pos + 1);
84 }
85 }
86 if (serverAddress.empty() || serverPort.empty())
87 {
88 return {};
89 }
90 try
91 {
92 uint32_t port = std::stoul(serverPort);
93 return std::make_pair(std::move(serverAddress), port);
94 }
95 catch (const std::exception& ex)
96 {
97 log<level::ERR>("Invalid config", entry("ERR=%s", ex.what()));
98 return {};
99 }
100}
101
102} // namespace internal
103
Deepak Kodihallic4966192018-08-23 02:19:58 -0500104std::string Server::address(std::string value)
105{
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500106 using Argument = xyz::openbmc_project::Common::InvalidArgument;
Patrick Venturef18bf832018-10-26 18:14:00 -0700107 std::string result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500108
109 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500110 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500111 auto serverAddress = address();
112 if (serverAddress == value)
113 {
114 return serverAddress;
115 }
116
117 if (!value.empty() && !addressValid(value))
118 {
119 elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
120 Argument::ARGUMENT_VALUE(value.c_str()));
121 }
122
123 writeConfig(value, port(), configFilePath.c_str());
124 result = std::move(NetworkClient::address(value));
125 }
126 catch (const InvalidArgument& e)
127 {
128 throw;
129 }
130 catch (const InternalFailure& e)
131 {
132 throw;
133 }
134 catch (const std::exception& e)
135 {
136 log<level::ERR>(e.what());
137 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500138 }
139
Deepak Kodihallic4966192018-08-23 02:19:58 -0500140 return result;
141}
142
143uint16_t Server::port(uint16_t value)
144{
Patrick Venturef18bf832018-10-26 18:14:00 -0700145 uint16_t result{};
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500146
147 try
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500148 {
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500149 auto serverPort = port();
150 if (serverPort == value)
151 {
152 return serverPort;
153 }
154
155 writeConfig(address(), value, configFilePath.c_str());
156 result = NetworkClient::port(value);
157 }
158 catch (const InternalFailure& e)
159 {
160 throw;
161 }
162 catch (const std::exception& e)
163 {
164 log<level::ERR>(e.what());
165 elog<InternalFailure>();
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500166 }
167
Deepak Kodihallic4966192018-08-23 02:19:58 -0500168 return result;
169}
170
Patrick Venturef18bf832018-10-26 18:14:00 -0700171void Server::writeConfig(const std::string& serverAddress, uint16_t serverPort,
172 const char* filePath)
Deepak Kodihallic4966192018-08-23 02:19:58 -0500173{
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500174 std::fstream stream(filePath, std::fstream::out);
175
Deepak Kodihallic4966192018-08-23 02:19:58 -0500176 if (serverPort && !serverAddress.empty())
177 {
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500178 // write '*.* @@<remote-host>:<port>'
Lei YUa1c43382021-04-15 20:26:25 +0800179 if (internal::isIPv6Address(serverAddress))
180 {
181 stream << "*.* @@[" << serverAddress << "]:" << serverPort;
182 }
183 else
184 {
185 stream << "*.* @@" << serverAddress << ":" << serverPort;
186 }
Deepak Kodihallic4966192018-08-23 02:19:58 -0500187 }
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500188 else // this is a disable request
189 {
Santosh Puranik0a0b5ea2019-05-22 05:25:30 -0500190 // write '*.* ~' - this causes rsyslog to discard all messages
191 stream << "*.* ~";
Deepak Kodihalli0febd262018-08-27 05:45:02 -0500192 }
193
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500194 restart();
Deepak Kodihallic4966192018-08-23 02:19:58 -0500195}
196
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500197bool Server::addressValid(const std::string& address)
198{
199 addrinfo hints{};
200 addrinfo* res = nullptr;
201 hints.ai_family = AF_UNSPEC;
202 hints.ai_socktype = SOCK_STREAM;
203 hints.ai_flags |= AI_CANONNAME;
204
205 auto result = getaddrinfo(address.c_str(), nullptr, &hints, &res);
206 if (result)
207 {
Patrick Venturef18bf832018-10-26 18:14:00 -0700208 log<level::ERR>("bad address", entry("ADDRESS=%s", address.c_str()),
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500209 entry("ERRNO=%d", result));
210 return false;
211 }
Patrick Williamsa40c2162021-04-22 09:11:10 -0500212
213 freeaddrinfo(res);
Deepak Kodihalli4db81462018-08-27 06:01:46 -0500214 return true;
215}
216
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500217void Server::restore(const char* filePath)
218{
219 std::fstream stream(filePath, std::fstream::in);
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500220
Lei YUa1c43382021-04-15 20:26:25 +0800221 auto ret = internal::parseConfig(stream);
222 if (ret)
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500223 {
Lei YUa1c43382021-04-15 20:26:25 +0800224 NetworkClient::address(ret->first);
225 NetworkClient::port(ret->second);
Deepak Kodihalli9fab2792018-08-28 07:47:11 -0500226 }
227}
228
Deepak Kodihalli2ce7b2c2018-08-31 04:22:55 -0500229void Server::restart()
230{
231 utils::restart();
232}
233
Deepak Kodihallic4966192018-08-23 02:19:58 -0500234} // namespace rsyslog_config
235} // namespace phosphor