File: address_tracker_linux_test_util.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (145 lines) | stat: -rw-r--r-- 4,394 bytes parent folder | download | duplicates (5)
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