1 #pragma once
2 
3 #include "xyz/openbmc_project/Network/Client/server.hpp"
4 
5 #include <phosphor-logging/log.hpp>
6 #include <sdbusplus/bus.hpp>
7 #include <sdbusplus/server/object.hpp>
8 
9 #include <string>
10 
11 namespace phosphor
12 {
13 namespace rsyslog_config
14 {
15 
16 using namespace phosphor::logging;
17 using NetworkClient = sdbusplus::xyz::openbmc_project::Network::server::Client;
18 using Iface = sdbusplus::server::object_t<NetworkClient>;
19 namespace sdbusRule = sdbusplus::bus::match::rules;
20 
21 /** @class Server
22  *  @brief Configuration for rsyslog server
23  *  @details A concrete implementation of the
24  *  xyz.openbmc_project.Network.Client API, in order to
25  *  provide remote rsyslog server's address and port.
26  */
27 class Server : public Iface
28 {
29   public:
30     Server() = delete;
31     Server(const Server&) = delete;
32     Server& operator=(const Server&) = delete;
33     Server(Server&&) = delete;
34     Server& operator=(Server&&) = delete;
35     virtual ~Server() = default;
36 
37     /** @brief Constructor to put object onto bus at a dbus path.
38      *  @param[in] bus - Bus to attach to.
39      *  @param[in] path - Path to attach at.
40      *  @param[in] filePath - rsyslog remote logging config file
41      */
42     Server(sdbusplus::bus_t& bus, const std::string& path,
43            const char* filePath) :
44         Iface(bus, path.c_str(), Iface::action::defer_emit),
45         configFilePath(filePath),
46         hostnameChange(
47             bus,
48             sdbusRule::propertiesChanged("/org/freedesktop/hostname1",
49                                          "org.freedesktop.hostname1"),
50             std::bind(std::mem_fn(&Server::hostnameChanged), this,
51                       std::placeholders::_1))
52     {
53         try
54         {
55             restore(configFilePath.c_str());
56         }
57         catch (const std::exception& e)
58         {
59             log<level::ERR>(e.what());
60         }
61 
62         emit_object_added();
63     }
64 
65     using NetworkClient::address;
66     using NetworkClient::port;
67 
68     /** @brief Override that updates rsyslog config file as well
69      *  @param[in] value - remote server address
70      *  @returns value of changed address
71      */
72     virtual std::string address(std::string value) override;
73 
74     /** @brief Override that updates rsyslog config file as well
75      *  @param[in] value - remote server port
76      *  @returns value of changed port
77      */
78     virtual uint16_t port(uint16_t value) override;
79 
80     /** @brief Restart rsyslog's systemd unit
81      */
82     virtual void restart();
83 
84   private:
85     /** @brief Update remote server address and port in
86      *         rsyslog config file.
87      *  @param[in] serverAddress - remote server address
88      *  @param[in] serverPort - remote server port
89      *  @param[in] filePath - rsyslog config file path
90      */
91     void writeConfig(const std::string& serverAddress, uint16_t serverPort,
92                      const char* filePath);
93 
94     /** @brief Checks if input IP address is valid (uses getaddrinfo)
95      *  @param[in] address - server address
96      *  @returns true if valid, false otherwise
97      */
98     bool addressValid(const std::string& address);
99 
100     /** @brief Populate existing config into D-Bus properties
101      *  @param[in] filePath - rsyslog config file path
102      */
103     void restore(const char* filePath);
104 
105     std::string configFilePath{};
106 
107     /** @brief React to hostname change
108      *  @param[in] msg - sdbusplus message
109      */
110     void hostnameChanged(sdbusplus::message_t& /*msg*/)
111     {
112         restart();
113     }
114 
115     sdbusplus::bus::match_t hostnameChange;
116 };
117 
118 } // namespace rsyslog_config
119 } // namespace phosphor
120