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