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