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