1 #include "system_configuration.hpp"
2 
3 #include <phosphor-logging/elog-errors.hpp>
4 #include <phosphor-logging/lg2.hpp>
5 #include <stdplus/pinned.hpp>
6 #include <xyz/openbmc_project/Common/error.hpp>
7 
8 namespace phosphor
9 {
10 namespace network
11 {
12 
13 static constexpr char HOSTNAMED_SVC[] = "org.freedesktop.hostname1";
14 static constexpr char HOSTNAMED_OBJ[] = "/org/freedesktop/hostname1";
15 static constexpr char HOSTNAMED_INTF[] = "org.freedesktop.hostname1";
16 
17 using namespace phosphor::logging;
18 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
19 using Argument = xyz::openbmc_project::Common::InvalidArgument;
20 
21 static constexpr char propMatch[] =
22     "type='signal',sender='org.freedesktop.hostname1',"
23     "path='/org/freedesktop/hostname1',"
24     "interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',"
25     "arg0='org.freedesktop.hostname1'";
26 
SystemConfiguration(stdplus::PinnedRef<sdbusplus::bus_t> bus,stdplus::const_zstring objPath)27 SystemConfiguration::SystemConfiguration(
28     stdplus::PinnedRef<sdbusplus::bus_t> bus, stdplus::const_zstring objPath) :
29     Iface(bus, objPath.c_str(), Iface::action::defer_emit),
30     bus(bus), hostnamePropMatch(
31                   bus, propMatch,
32                   [sc = stdplus::PinnedRef(*this)](sdbusplus::message_t& m) {
33     std::string intf;
34     std::unordered_map<std::string, std::variant<std::string>> values;
35     try
36     {
37         m.read(intf, values);
38         auto it = values.find("Hostname");
39         if (it == values.end())
40         {
41             return;
42         }
43         sc.get().Iface::hostName(std::get<std::string>(it->second));
44     }
45     catch (const std::exception& e)
46     {
47         lg2::error("Hostname match parsing failed: {ERROR}", "ERROR", e);
48     }
49 })
50 {
51     try
52     {
53         std::variant<std::string> name;
54         auto req = bus.get().new_method_call(HOSTNAMED_SVC, HOSTNAMED_OBJ,
55                                              "org.freedesktop.DBus.Properties",
56                                              "Get");
57 
58         req.append(HOSTNAMED_INTF, "Hostname");
59         auto reply = req.call();
60         reply.read(name);
61         SystemConfigIntf::hostName(std::get<std::string>(name), true);
62     }
63     catch (const std::exception& e)
64     {
65         lg2::error("Failed to get hostname: {ERROR}", "ERROR", e);
66     }
67 
68     emit_object_added();
69 }
70 
hostName(std::string name)71 std::string SystemConfiguration::hostName(std::string name)
72 {
73     if (SystemConfigIntf::hostName() == name)
74     {
75         return name;
76     }
77     try
78     {
79         auto method = bus.get().new_method_call(
80             HOSTNAMED_SVC, HOSTNAMED_OBJ, HOSTNAMED_INTF, "SetStaticHostname");
81         method.append(name, /*interactive=*/false);
82         method.call();
83         return SystemConfigIntf::hostName(std::move(name));
84     }
85     catch (const sdbusplus::exception::SdBusError& e)
86     {
87         lg2::error("Failed to set hostname {HOSTNAME}: {ERROR} ", "HOSTNAME",
88                    name, "ERROR", e);
89         auto dbusError = e.get_error();
90         if ((dbusError != nullptr) &&
91             (strcmp(dbusError->name,
92                     "org.freedesktop.DBus.Error.InvalidArgs") == 0))
93         {
94             elog<InvalidArgument>(Argument::ARGUMENT_NAME("Hostname"),
95                                   Argument::ARGUMENT_VALUE(name.c_str()));
96         }
97     }
98     return SystemConfigIntf::hostName();
99 }
100 
101 } // namespace network
102 } // namespace phosphor
103