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