blob: 647c37e5bbe75715958357c5211d219f0e36dbb5 [file] [log] [blame]
Ratan Gupta2eff84f2017-04-20 19:19:15 +05301#include "ipaddress.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
Ratan Gupta2eff84f2017-04-20 19:19:15 +05303#include "ethernet_interface.hpp"
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -07004#include "netlink.hpp"
William A. Kennington III59e5b912022-11-02 02:49:46 -07005#include "network_manager.hpp"
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -05006#include "util.hpp"
Ratan Gupta2eff84f2017-04-20 19:19:15 +05307
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -07008#include <linux/netlink.h>
9#include <linux/rtnetlink.h>
10
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050011#include <phosphor-logging/elog-errors.hpp>
Patrick Venture189d44e2018-07-09 12:30:59 -070012#include <phosphor-logging/log.hpp>
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -070013#include <stdexcept>
14#include <stdplus/raw.hpp>
15#include <string>
16#include <string_view>
17#include <vector>
Patrick Venture189d44e2018-07-09 12:30:59 -070018#include <xyz/openbmc_project/Common/error.hpp>
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -070019
Ratan Gupta2eff84f2017-04-20 19:19:15 +053020namespace phosphor
21{
22namespace network
23{
24
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -070025std::vector<AddressInfo> getCurrentAddresses(const AddressFilter& filter)
26{
27 std::vector<AddressInfo> addresses;
28 auto cb = [&filter, &addresses](const nlmsghdr& hdr, std::string_view msg) {
29 detail::parseAddress(filter, hdr, msg, addresses);
30 };
31 ifaddrmsg msg{};
32 msg.ifa_index = filter.interface;
33 netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb);
34 return addresses;
35}
36
Ratan Gupta2eff84f2017-04-20 19:19:15 +053037using namespace phosphor::logging;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050038using namespace sdbusplus::xyz::openbmc_project::Common::Error;
William A. Kennington III5e72d082022-09-01 13:10:17 -070039using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
40using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
Ratan Gupta2eff84f2017-04-20 19:19:15 +053041
William A. Kennington III59e5b912022-11-02 02:49:46 -070042static auto makeObjPath(std::string_view root, IfAddr addr)
Ratan Gupta2eff84f2017-04-20 19:19:15 +053043{
William A. Kennington III59e5b912022-11-02 02:49:46 -070044 auto ret = sdbusplus::message::object_path(std::string(root));
45 ret /= std::to_string(addr);
46 return ret;
47}
Ravi Teja2fd2f7d2019-06-06 03:27:55 -050048
William A. Kennington III59e5b912022-11-02 02:49:46 -070049template <typename T>
50struct Proto
51{
52};
53
54template <>
55struct Proto<in_addr>
56{
57 static inline constexpr auto value = IP::Protocol::IPv4;
58};
59
60template <>
61struct Proto<in6_addr>
62{
63 static inline constexpr auto value = IP::Protocol::IPv6;
64};
65
66IPAddress::IPAddress(sdbusplus::bus_t& bus, std::string_view objRoot,
67 EthernetInterface& parent, IfAddr addr,
68 AddressOrigin origin) :
69 IPAddress(bus, makeObjPath(objRoot, addr), parent, addr, origin)
70{
71}
72
73IPAddress::IPAddress(sdbusplus::bus_t& bus,
74 sdbusplus::message::object_path objPath,
75 EthernetInterface& parent, IfAddr addr,
76 AddressOrigin origin) :
77 IPIfaces(bus, objPath.str.c_str(), IPIfaces::action::defer_emit),
78 parent(parent), objPath(std::move(objPath))
79{
80 IP::address(std::to_string(addr.getAddr()));
81 IP::prefixLength(addr.getPfx());
82 IP::type(std::visit([](auto v) { return Proto<decltype(v)>::value; },
83 addr.getAddr()));
Ravi Teja2fd2f7d2019-06-06 03:27:55 -050084 IP::origin(origin);
Ratan Gupta29b0e432017-05-25 12:51:40 +053085
Gunnar Mills57d9c502018-09-14 14:42:34 -050086 // Emit deferred signal.
87 emit_object_added();
Ratan Gupta2eff84f2017-04-20 19:19:15 +053088}
William A. Kennington III5e72d082022-09-01 13:10:17 -070089std::string IPAddress::address(std::string /*ipAddress*/)
90{
91 elog<NotAllowed>(Reason("Property update is not allowed"));
92}
93uint8_t IPAddress::prefixLength(uint8_t /*value*/)
94{
95 elog<NotAllowed>(Reason("Property update is not allowed"));
96}
97std::string IPAddress::gateway(std::string /*gateway*/)
98{
99 elog<NotAllowed>(Reason("Property update is not allowed"));
100}
101IP::Protocol IPAddress::type(IP::Protocol /*type*/)
102{
103 elog<NotAllowed>(Reason("Property update is not allowed"));
104}
105IP::AddressOrigin IPAddress::origin(IP::AddressOrigin /*origin*/)
106{
107 elog<NotAllowed>(Reason("Property update is not allowed"));
108}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530109void IPAddress::delete_()
110{
William A. Kennington III2dae9692019-04-22 02:18:41 -0700111 if (origin() != IP::AddressOrigin::Static)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500112 {
William A. Kennington III2dae9692019-04-22 02:18:41 -0700113 log<level::ERR>("Tried to delete a non-static address"),
114 entry("ADDRESS=%s", address().c_str()),
115 entry("PREFIX=%" PRIu8, prefixLength()),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500116 entry("INTERFACE=%s", parent.interfaceName().c_str());
William A. Kennington III2dae9692019-04-22 02:18:41 -0700117 elog<InternalFailure>();
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500118 }
119
William A. Kennington III59e5b912022-11-02 02:49:46 -0700120 std::unique_ptr<IPAddress> ptr;
121 for (auto it = parent.addrs.begin(); it != parent.addrs.end(); ++it)
122 {
123 if (it->second.get() == this)
124 {
125 ptr = std::move(it->second);
126 parent.addrs.erase(it);
127 break;
128 }
129 }
130
131 parent.writeConfigurationFile();
132 parent.manager.reloadConfigs();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530133}
134
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700135namespace detail
136{
137
138void parseAddress(const AddressFilter& filter, const nlmsghdr& hdr,
139 std::string_view msg, std::vector<AddressInfo>& addresses)
140{
141 if (hdr.nlmsg_type != RTM_NEWADDR)
142 {
143 throw std::runtime_error("Not an address msg");
144 }
William A. Kennington IIIf1289a02022-10-24 18:30:36 -0700145 const auto& ifaddr = netlink::extractRtData<ifaddrmsg>(msg);
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700146
147 // Filter out addresses we don't care about
148 unsigned ifindex = ifaddr.ifa_index;
149 if (filter.interface != 0 && filter.interface != ifindex)
150 {
151 return;
152 }
153 if (filter.scope && *filter.scope != ifaddr.ifa_scope)
154 {
155 return;
156 }
157
158 // Build the info about the address we found
159 AddressInfo address;
160 address.interface = ifindex;
161 address.prefix = ifaddr.ifa_prefixlen;
162 address.flags = ifaddr.ifa_flags;
163 address.scope = ifaddr.ifa_scope;
164 bool set_addr = false;
165 while (!msg.empty())
166 {
167 auto [hdr, data] = netlink::extractRtAttr(msg);
168 if (hdr.rta_type == IFA_ADDRESS)
169 {
170 address.address = addrFromBuf(ifaddr.ifa_family, data);
171 set_addr = true;
172 }
173 else if (hdr.rta_type == IFA_FLAGS)
174 {
175 address.flags = stdplus::raw::extract<uint32_t>(data);
176 }
177 }
178 if (!set_addr)
179 {
180 throw std::runtime_error("Missing address");
181 }
182 addresses.push_back(std::move(address));
183}
184
185} // namespace detail
Gunnar Mills57d9c502018-09-14 14:42:34 -0500186} // namespace network
187} // namespace phosphor