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 namespace phosphor
17 {
18 namespace rsyslog_config
19 {
20 
21 namespace utils = phosphor::rsyslog_utils;
22 using namespace phosphor::logging;
23 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
24 
25 std::string Server::address(std::string value)
26 {
27     using Argument = xyz::openbmc_project::Common::InvalidArgument;
28     std::string result{};
29 
30     try
31     {
32         auto serverAddress = address();
33         if (serverAddress == value)
34         {
35             return serverAddress;
36         }
37 
38         if (!value.empty() && !addressValid(value))
39         {
40             elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
41                                   Argument::ARGUMENT_VALUE(value.c_str()));
42         }
43 
44         writeConfig(value, port(), configFilePath.c_str());
45         result = std::move(NetworkClient::address(value));
46     }
47     catch (const InvalidArgument& e)
48     {
49         throw;
50     }
51     catch (const InternalFailure& e)
52     {
53         throw;
54     }
55     catch (const std::exception& e)
56     {
57         log<level::ERR>(e.what());
58         elog<InternalFailure>();
59     }
60 
61     return result;
62 }
63 
64 uint16_t Server::port(uint16_t value)
65 {
66     uint16_t result{};
67 
68     try
69     {
70         auto serverPort = port();
71         if (serverPort == value)
72         {
73             return serverPort;
74         }
75 
76         writeConfig(address(), value, configFilePath.c_str());
77         result = NetworkClient::port(value);
78     }
79     catch (const InternalFailure& e)
80     {
81         throw;
82     }
83     catch (const std::exception& e)
84     {
85         log<level::ERR>(e.what());
86         elog<InternalFailure>();
87     }
88 
89     return result;
90 }
91 
92 void Server::writeConfig(const std::string& serverAddress, 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", entry("ADDRESS=%s", address.c_str()),
123                         entry("ERRNO=%d", result));
124         return false;
125     }
126     return true;
127 }
128 
129 void Server::restore(const char* filePath)
130 {
131     std::fstream stream(filePath, std::fstream::in);
132     std::string line;
133 
134     getline(stream, line);
135 
136     // Ignore if line is commented
137     if ('#' != line.at(0))
138     {
139         auto pos = line.find(':');
140         if (pos != std::string::npos)
141         {
142             //"*.* @@<address>:<port>"
143             constexpr auto start = 6; // Skip "*.* @@"
144             auto serverAddress = line.substr(start, pos - start);
145             auto serverPort = line.substr(pos + 1);
146             NetworkClient::address(std::move(serverAddress));
147             NetworkClient::port(std::stoul(serverPort));
148         }
149     }
150 }
151 
152 void Server::restart()
153 {
154     utils::restart();
155 }
156 
157 } // namespace rsyslog_config
158 } // namespace phosphor
159