#include "ipaddress.hpp" #include "ethernet_interface.hpp" #include "netlink.hpp" #include "util.hpp" #include #include #include #include #include #include #include #include #include #include namespace phosphor { namespace network { std::vector getCurrentAddresses(const AddressFilter& filter) { std::vector addresses; auto cb = [&filter, &addresses](const nlmsghdr& hdr, std::string_view msg) { detail::parseAddress(filter, hdr, msg, addresses); }; ifaddrmsg msg{}; msg.ifa_index = filter.interface; netlink::performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, msg, cb); return addresses; } using namespace phosphor::logging; using namespace sdbusplus::xyz::openbmc_project::Common::Error; using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; using Reason = xyz::openbmc_project::Common::NotAllowed::REASON; IPAddress::IPAddress(sdbusplus::bus_t& bus, stdplus::const_zstring objPath, EthernetInterface& parent, IP::Protocol type, std::string_view ipaddress, IP::AddressOrigin origin, uint8_t prefixLength) : IPIfaces(bus, objPath.c_str(), IPIfaces::action::defer_emit), parent(parent) { IP::address(std::string(ipaddress)); IP::prefixLength(prefixLength); IP::type(type); IP::origin(origin); // Emit deferred signal. emit_object_added(); } std::string IPAddress::address(std::string /*ipAddress*/) { elog(Reason("Property update is not allowed")); } uint8_t IPAddress::prefixLength(uint8_t /*value*/) { elog(Reason("Property update is not allowed")); } std::string IPAddress::gateway(std::string /*gateway*/) { elog(Reason("Property update is not allowed")); } IP::Protocol IPAddress::type(IP::Protocol /*type*/) { elog(Reason("Property update is not allowed")); } IP::AddressOrigin IPAddress::origin(IP::AddressOrigin /*origin*/) { elog(Reason("Property update is not allowed")); } void IPAddress::delete_() { if (origin() != IP::AddressOrigin::Static) { log("Tried to delete a non-static address"), entry("ADDRESS=%s", address().c_str()), entry("PREFIX=%" PRIu8, prefixLength()), entry("INTERFACE=%s", parent.interfaceName().c_str()); elog(); } parent.deleteObject(address()); } namespace detail { void parseAddress(const AddressFilter& filter, const nlmsghdr& hdr, std::string_view msg, std::vector& addresses) { if (hdr.nlmsg_type != RTM_NEWADDR) { throw std::runtime_error("Not an address msg"); } auto ifaddr = stdplus::raw::extract(msg); // Filter out addresses we don't care about unsigned ifindex = ifaddr.ifa_index; if (filter.interface != 0 && filter.interface != ifindex) { return; } if (filter.scope && *filter.scope != ifaddr.ifa_scope) { return; } // Build the info about the address we found AddressInfo address; address.interface = ifindex; address.prefix = ifaddr.ifa_prefixlen; address.flags = ifaddr.ifa_flags; address.scope = ifaddr.ifa_scope; bool set_addr = false; while (!msg.empty()) { auto [hdr, data] = netlink::extractRtAttr(msg); if (hdr.rta_type == IFA_ADDRESS) { address.address = addrFromBuf(ifaddr.ifa_family, data); set_addr = true; } else if (hdr.rta_type == IFA_FLAGS) { address.flags = stdplus::raw::extract(data); } } if (!set_addr) { throw std::runtime_error("Missing address"); } addresses.push_back(std::move(address)); } } // namespace detail } // namespace network } // namespace phosphor