1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/base/address_tracker_linux_test_util.h"
11
12 #include <linux/if.h>
13 #include <linux/netlink.h>
14 #include <linux/rtnetlink.h>
15 #include <stdint.h>
16 #include <string.h>
17
18 #include <vector>
19
20 #include "base/check_op.h"
21 #include "base/logging.h"
22 #include "net/base/ip_address.h"
23
operator ==(const struct ifaddrmsg & lhs,const struct ifaddrmsg & rhs)24 bool operator==(const struct ifaddrmsg& lhs, const struct ifaddrmsg& rhs) {
25 return memcmp(&lhs, &rhs, sizeof(struct ifaddrmsg)) == 0;
26 }
27
28 namespace net::test {
29
NetlinkMessage(uint16_t type)30 NetlinkMessage::NetlinkMessage(uint16_t type) : buffer_(NLMSG_HDRLEN) {
31 header()->nlmsg_type = type;
32 Align();
33 }
34
35 NetlinkMessage::~NetlinkMessage() = default;
36
AddPayload(const void * data,size_t length)37 void NetlinkMessage::AddPayload(const void* data, size_t length) {
38 CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN), buffer_.size())
39 << "Payload must be added first";
40 Append(data, length);
41 Align();
42 }
43
AddAttribute(uint16_t type,const void * data,size_t length)44 void NetlinkMessage::AddAttribute(uint16_t type,
45 const void* data,
46 size_t length) {
47 struct nlattr attr;
48 attr.nla_len = NLA_HDRLEN + length;
49 attr.nla_type = type;
50 Append(&attr, sizeof(attr));
51 Align();
52 Append(data, length);
53 Align();
54 }
55
AppendTo(NetlinkBuffer * output) const56 void NetlinkMessage::AppendTo(NetlinkBuffer* output) const {
57 CHECK_EQ(NLMSG_ALIGN(output->size()), output->size());
58 output->insert(output->end(), buffer_.begin(), buffer_.end());
59 }
60
Append(const void * data,size_t length)61 void NetlinkMessage::Append(const void* data, size_t length) {
62 const char* chardata = reinterpret_cast<const char*>(data);
63 buffer_.insert(buffer_.end(), chardata, chardata + length);
64 }
65
Align()66 void NetlinkMessage::Align() {
67 header()->nlmsg_len = buffer_.size();
68 buffer_.resize(NLMSG_ALIGN(buffer_.size()));
69 CHECK(NLMSG_OK(header(), buffer_.size()));
70 }
71
72 #define INFINITY_LIFE_TIME 0xFFFFFFFF
73
MakeAddrMessageWithCacheInfo(uint16_t type,uint8_t flags,uint8_t family,int index,const IPAddress & address,const IPAddress & local,uint32_t preferred_lifetime,NetlinkBuffer * output)74 void MakeAddrMessageWithCacheInfo(uint16_t type,
75 uint8_t flags,
76 uint8_t family,
77 int index,
78 const IPAddress& address,
79 const IPAddress& local,
80 uint32_t preferred_lifetime,
81 NetlinkBuffer* output) {
82 NetlinkMessage nlmsg(type);
83 struct ifaddrmsg msg = {};
84 msg.ifa_family = family;
85 msg.ifa_flags = flags;
86 msg.ifa_index = index;
87 nlmsg.AddPayload(msg);
88 if (address.size()) {
89 nlmsg.AddAttribute(IFA_ADDRESS, address.bytes().data(), address.size());
90 }
91 if (local.size()) {
92 nlmsg.AddAttribute(IFA_LOCAL, local.bytes().data(), local.size());
93 }
94 struct ifa_cacheinfo cache_info = {};
95 cache_info.ifa_prefered = preferred_lifetime;
96 cache_info.ifa_valid = INFINITY_LIFE_TIME;
97 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
98 nlmsg.AppendTo(output);
99 }
100
MakeAddrMessage(uint16_t type,uint8_t flags,uint8_t family,int index,const IPAddress & address,const IPAddress & local,NetlinkBuffer * output)101 void MakeAddrMessage(uint16_t type,
102 uint8_t flags,
103 uint8_t family,
104 int index,
105 const IPAddress& address,
106 const IPAddress& local,
107 NetlinkBuffer* output) {
108 MakeAddrMessageWithCacheInfo(type, flags, family, index, address, local,
109 INFINITY_LIFE_TIME, output);
110 }
111
MakeLinkMessage(uint16_t type,uint32_t flags,uint32_t index,NetlinkBuffer * output,bool clear_output)112 void MakeLinkMessage(uint16_t type,
113 uint32_t flags,
114 uint32_t index,
115 NetlinkBuffer* output,
116 bool clear_output) {
117 NetlinkMessage nlmsg(type);
118 struct ifinfomsg msg = {};
119 msg.ifi_index = index;
120 msg.ifi_flags = flags;
121 msg.ifi_change = 0xFFFFFFFF;
122 nlmsg.AddPayload(msg);
123 if (clear_output) {
124 output->clear();
125 }
126 nlmsg.AppendTo(output);
127 }
128
129 // Creates a netlink message generated by wireless_send_event. These events
130 // should be ignored.
MakeWirelessLinkMessage(uint16_t type,uint32_t flags,uint32_t index,NetlinkBuffer * output,bool clear_output)131 void MakeWirelessLinkMessage(uint16_t type,
132 uint32_t flags,
133 uint32_t index,
134 NetlinkBuffer* output,
135 bool clear_output) {
136 NetlinkMessage nlmsg(type);
137 struct ifinfomsg msg = {};
138 msg.ifi_index = index;
139 msg.ifi_flags = flags;
140 msg.ifi_change = 0;
141 nlmsg.AddPayload(msg);
142 char data[8] = {0};
143 nlmsg.AddAttribute(IFLA_WIRELESS, data, sizeof(data));
144 if (clear_output) {
145 output->clear();
146 }
147 nlmsg.AppendTo(output);
148 }
149
150 } // namespace net::test
151