• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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