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