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