1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// 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
|