xref: /aosp_15_r20/external/cronet/net/base/address_tracker_linux_test_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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