1 #include "server-conf.hpp"
2 #include "utils.hpp"
3 #include "xyz/openbmc_project/Common/error.hpp"
4 #include <fstream>
5 #include <phosphor-logging/elog.hpp>
6 #if __has_include("../../usr/include/phosphor-logging/elog-errors.hpp")
7 #include "../../usr/include/phosphor-logging/elog-errors.hpp"
8 #else
9 #include <phosphor-logging/elog-errors.hpp>
10 #endif
11 #include <netdb.h>
12 #include <arpa/inet.h>
13 
14 namespace phosphor
15 {
16 namespace rsyslog_config
17 {
18 
19 namespace utils = phosphor::rsyslog_utils;
20 using namespace phosphor::logging;
21 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
22 
23 std::string Server::address(std::string value)
24 {
25     using Argument = xyz::openbmc_project::Common::InvalidArgument;
26     std::string result {};
27 
28     try
29     {
30         auto serverAddress = address();
31         if (serverAddress == value)
32         {
33             return serverAddress;
34         }
35 
36         if (!value.empty() && !addressValid(value))
37         {
38             elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
39                                   Argument::ARGUMENT_VALUE(value.c_str()));
40         }
41 
42         writeConfig(value, port(), configFilePath.c_str());
43         result = std::move(NetworkClient::address(value));
44     }
45     catch (const InvalidArgument& e)
46     {
47         throw;
48     }
49     catch (const InternalFailure& e)
50     {
51         throw;
52     }
53     catch (const std::exception& e)
54     {
55         log<level::ERR>(e.what());
56         elog<InternalFailure>();
57     }
58 
59     return result;
60 }
61 
62 uint16_t Server::port(uint16_t value)
63 {
64     uint16_t result {};
65 
66     try
67     {
68         auto serverPort = port();
69         if (serverPort == value)
70         {
71             return serverPort;
72         }
73 
74         writeConfig(address(), value, configFilePath.c_str());
75         result = NetworkClient::port(value);
76     }
77     catch (const InternalFailure& e)
78     {
79         throw;
80     }
81     catch (const std::exception& e)
82     {
83         log<level::ERR>(e.what());
84         elog<InternalFailure>();
85     }
86 
87     return result;
88 }
89 
90 void Server::writeConfig(
91                  const std::string& serverAddress,
92                  uint16_t serverPort,
93                  const char* filePath)
94 {
95     std::fstream stream(filePath, std::fstream::out);
96 
97     if (serverPort && !serverAddress.empty())
98     {
99         // write '*.* @@<remote-host>:<port>'
100         stream << "*.* @@" << serverAddress << ":" << serverPort;
101     }
102     else // this is a disable request
103     {
104         // write '#*.* @@remote-host:port'
105         stream << "#*.* @@remote-host:port";
106     }
107 
108     restart();
109 }
110 
111 bool Server::addressValid(const std::string& address)
112 {
113     addrinfo hints{};
114     addrinfo* res = nullptr;
115     hints.ai_family = AF_UNSPEC;
116     hints.ai_socktype = SOCK_STREAM;
117     hints.ai_flags |= AI_CANONNAME;
118 
119     auto result = getaddrinfo(address.c_str(), nullptr, &hints, &res);
120     if (result)
121     {
122         log<level::ERR>("bad address",
123                         entry("ADDRESS=%s", address.c_str()),
124                         entry("ERRNO=%d", result));
125         return false;
126     }
127     return true;
128 }
129 
130 void Server::restore(const char* filePath)
131 {
132     std::fstream stream(filePath, std::fstream::in);
133     std::string line;
134 
135     getline(stream, line);
136 
137     // Ignore if line is commented
138     if ('#' != line.at(0))
139     {
140         auto pos = line.find(':');
141         if (pos != std::string::npos)
142         {
143             //"*.* @@<address>:<port>"
144             constexpr auto start = 6; // Skip "*.* @@"
145             auto serverAddress = line.substr(start, pos - start);
146             auto serverPort = line.substr(pos + 1);
147             NetworkClient::address(std::move(serverAddress));
148             NetworkClient::port(std::stoul(serverPort));
149         }
150     }
151 }
152 
153 void Server::restart()
154 {
155     utils::restart();
156 }
157 
158 } // namespace rsyslog_config
159 } // namespace phosphor
160