| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/address_tracker_linux_test_util.h" |
| |
| #include <linux/if.h> |
| #include <linux/netlink.h> |
| #include <linux/rtnetlink.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include <array> |
| #include <vector> |
| |
| #include "base/check_op.h" |
| #include "base/containers/span.h" |
| #include "base/logging.h" |
| #include "net/base/ip_address.h" |
| |
| bool operator==(const struct ifaddrmsg& lhs, const struct ifaddrmsg& rhs) { |
| return base::byte_span_from_ref(lhs) == base::byte_span_from_ref(rhs); |
| } |
| |
| namespace net::test { |
| |
| NetlinkMessage::NetlinkMessage(uint16_t type) : buffer_(NLMSG_HDRLEN) { |
| header()->nlmsg_type = type; |
| Align(); |
| } |
| |
| NetlinkMessage::~NetlinkMessage() = default; |
| |
| void NetlinkMessage::AddPayload(base::span<const uint8_t> data) { |
| CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN), buffer_.size()) |
| << "Payload must be added first"; |
| Append(data); |
| Align(); |
| } |
| |
| void NetlinkMessage::AddAttribute(uint16_t type, |
| base::span<const uint8_t> data) { |
| struct nlattr attr; |
| attr.nla_len = NLA_HDRLEN + data.size(); |
| attr.nla_type = type; |
| Append(base::byte_span_from_ref(attr)); |
| Align(); |
| Append(data); |
| Align(); |
| } |
| |
| void NetlinkMessage::AppendTo(NetlinkBuffer* output) const { |
| CHECK_EQ(NLMSG_ALIGN(output->size()), output->size()); |
| output->insert(output->end(), buffer_.begin(), buffer_.end()); |
| } |
| |
| void NetlinkMessage::Append(base::span<const uint8_t> data) { |
| buffer_.insert(buffer_.end(), data.begin(), data.end()); |
| } |
| |
| void NetlinkMessage::Align() { |
| header()->nlmsg_len = buffer_.size(); |
| buffer_.resize(NLMSG_ALIGN(buffer_.size())); |
| CHECK(NLMSG_OK(header(), buffer_.size())); |
| } |
| |
| #define INFINITY_LIFE_TIME 0xFFFFFFFF |
| |
| void MakeAddrMessageWithCacheInfo(uint16_t type, |
| uint8_t flags, |
| uint8_t family, |
| int index, |
| const IPAddress& address, |
| const IPAddress& local, |
| uint32_t preferred_lifetime, |
| NetlinkBuffer* output) { |
| NetlinkMessage nlmsg(type); |
| ifaddrmsg msg = {}; |
| msg.ifa_family = family; |
| msg.ifa_flags = flags; |
| msg.ifa_index = index; |
| nlmsg.AddPayload(base::byte_span_from_ref(msg)); |
| if (address.size()) { |
| nlmsg.AddAttribute(IFA_ADDRESS, address.bytes().span()); |
| } |
| if (local.size()) { |
| nlmsg.AddAttribute(IFA_LOCAL, local.bytes().span()); |
| } |
| ifa_cacheinfo cache_info = {}; |
| cache_info.ifa_prefered = preferred_lifetime; |
| cache_info.ifa_valid = INFINITY_LIFE_TIME; |
| nlmsg.AddAttribute(IFA_CACHEINFO, base::byte_span_from_ref(cache_info)); |
| nlmsg.AppendTo(output); |
| } |
| |
| void MakeAddrMessage(uint16_t type, |
| uint8_t flags, |
| uint8_t family, |
| int index, |
| const IPAddress& address, |
| const IPAddress& local, |
| NetlinkBuffer* output) { |
| MakeAddrMessageWithCacheInfo(type, flags, family, index, address, local, |
| INFINITY_LIFE_TIME, output); |
| } |
| |
| void MakeLinkMessage(uint16_t type, |
| uint32_t flags, |
| uint32_t index, |
| NetlinkBuffer* output, |
| bool clear_output) { |
| NetlinkMessage nlmsg(type); |
| ifinfomsg msg = {}; |
| msg.ifi_index = index; |
| msg.ifi_flags = flags; |
| msg.ifi_change = 0xFFFFFFFF; |
| nlmsg.AddPayload(base::byte_span_from_ref(msg)); |
| if (clear_output) { |
| output->clear(); |
| } |
| nlmsg.AppendTo(output); |
| } |
| |
| // Creates a netlink message generated by wireless_send_event. These events |
| // should be ignored. |
| void MakeWirelessLinkMessage(uint16_t type, |
| uint32_t flags, |
| uint32_t index, |
| NetlinkBuffer* output, |
| bool clear_output) { |
| NetlinkMessage nlmsg(type); |
| ifinfomsg msg = {}; |
| msg.ifi_index = index; |
| msg.ifi_flags = flags; |
| msg.ifi_change = 0; |
| nlmsg.AddPayload(base::byte_span_from_ref(msg)); |
| std::array<uint8_t, 8u> data = {}; |
| nlmsg.AddAttribute(IFLA_WIRELESS, data); |
| if (clear_output) { |
| output->clear(); |
| } |
| nlmsg.AppendTo(output); |
| } |
| |
| } // namespace net::test |