1 #include "ipaddress.hpp"
2 
3 #include "ethernet_interface.hpp"
4 #include "netlink.hpp"
5 #include "util.hpp"
6 
7 #include <linux/netlink.h>
8 #include <linux/rtnetlink.h>
9 
10 #include <phosphor-logging/elog-errors.hpp>
11 #include <phosphor-logging/log.hpp>
12 #include <stdexcept>
13 #include <stdplus/raw.hpp>
14 #include <string>
15 #include <string_view>
16 #include <vector>
17 #include <xyz/openbmc_project/Common/error.hpp>
18 
19 namespace phosphor
20 {
21 namespace network
22 {
23 
24 std::vector<AddressInfo> getCurrentAddresses(const AddressFilter& filter)
25 {
26     std::vector<AddressInfo> addresses;
27     auto cb = [&filter, &addresses](const nlmsghdr& hdr, std::string_view msg) {
28         detail::parseAddress(filter, hdr, msg, addresses);
29     };
30     ifaddrmsg msg{};
31     msg.ifa_index = filter.interface;
32     netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb);
33     return addresses;
34 }
35 
36 using namespace phosphor::logging;
37 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
38 using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
39 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
40 
41 IPAddress::IPAddress(sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
42                      EthernetInterface& parent, IP::Protocol type,
43                      std::string_view ipaddress, IP::AddressOrigin origin,
44                      uint8_t prefixLength) :
45     IPIfaces(bus, objPath.c_str(), IPIfaces::action::defer_emit),
46     parent(parent)
47 {
48 
49     IP::address(std::string(ipaddress));
50     IP::prefixLength(prefixLength);
51     IP::type(type);
52     IP::origin(origin);
53 
54     // Emit deferred signal.
55     emit_object_added();
56 }
57 std::string IPAddress::address(std::string /*ipAddress*/)
58 {
59     elog<NotAllowed>(Reason("Property update is not allowed"));
60 }
61 uint8_t IPAddress::prefixLength(uint8_t /*value*/)
62 {
63     elog<NotAllowed>(Reason("Property update is not allowed"));
64 }
65 std::string IPAddress::gateway(std::string /*gateway*/)
66 {
67     elog<NotAllowed>(Reason("Property update is not allowed"));
68 }
69 IP::Protocol IPAddress::type(IP::Protocol /*type*/)
70 {
71     elog<NotAllowed>(Reason("Property update is not allowed"));
72 }
73 IP::AddressOrigin IPAddress::origin(IP::AddressOrigin /*origin*/)
74 {
75     elog<NotAllowed>(Reason("Property update is not allowed"));
76 }
77 void IPAddress::delete_()
78 {
79     if (origin() != IP::AddressOrigin::Static)
80     {
81         log<level::ERR>("Tried to delete a non-static address"),
82             entry("ADDRESS=%s", address().c_str()),
83             entry("PREFIX=%" PRIu8, prefixLength()),
84             entry("INTERFACE=%s", parent.interfaceName().c_str());
85         elog<InternalFailure>();
86     }
87 
88     parent.deleteObject(address());
89 }
90 
91 namespace detail
92 {
93 
94 void parseAddress(const AddressFilter& filter, const nlmsghdr& hdr,
95                   std::string_view msg, std::vector<AddressInfo>& addresses)
96 {
97     if (hdr.nlmsg_type != RTM_NEWADDR)
98     {
99         throw std::runtime_error("Not an address msg");
100     }
101     auto ifaddr = stdplus::raw::extract<ifaddrmsg>(msg);
102 
103     // Filter out addresses we don't care about
104     unsigned ifindex = ifaddr.ifa_index;
105     if (filter.interface != 0 && filter.interface != ifindex)
106     {
107         return;
108     }
109     if (filter.scope && *filter.scope != ifaddr.ifa_scope)
110     {
111         return;
112     }
113 
114     // Build the info about the address we found
115     AddressInfo address;
116     address.interface = ifindex;
117     address.prefix = ifaddr.ifa_prefixlen;
118     address.flags = ifaddr.ifa_flags;
119     address.scope = ifaddr.ifa_scope;
120     bool set_addr = false;
121     while (!msg.empty())
122     {
123         auto [hdr, data] = netlink::extractRtAttr(msg);
124         if (hdr.rta_type == IFA_ADDRESS)
125         {
126             address.address = addrFromBuf(ifaddr.ifa_family, data);
127             set_addr = true;
128         }
129         else if (hdr.rta_type == IFA_FLAGS)
130         {
131             address.flags = stdplus::raw::extract<uint32_t>(data);
132         }
133     }
134     if (!set_addr)
135     {
136         throw std::runtime_error("Missing address");
137     }
138     addresses.push_back(std::move(address));
139 }
140 
141 } // namespace detail
142 } // namespace network
143 } // namespace phosphor
144