summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h
blob: 9a5b7d9fac1846446ed853c5cc15e31052ae3000 (plain)
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
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_
#define QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_

#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "quic/platform/api/quic_ip_address.h"
#include "quic/qbone/platform/ip_range.h"
#include "quic/qbone/platform/kernel_interface.h"
#include "quic/qbone/platform/netlink_interface.h"

namespace quic {

// A wrapper class to provide convenient methods of manipulating IP address and
// routing table using netlink (man 7 netlink) socket. More specifically,
// rtnetlink is used (man 7 rtnetlink).
//
// This class is not thread safe, but thread compatible, as long as callers can
// make sure Send and Recv pairs are executed in sequence for a particular
// query.
class Netlink : public NetlinkInterface {
 public:
  explicit Netlink(KernelInterface* kernel);
  ~Netlink() override;

  // Gets the link information for the interface referred by the given
  // interface_name.
  //
  // This is a synchronous communication. That should not be a problem since the
  // kernel should answer immediately.
  bool GetLinkInfo(const std::string& interface_name,
                   LinkInfo* link_info) override;

  // Gets the addresses for the given interface referred by the given
  // interface_index.
  //
  // This is a synchronous communication. This should not be a problem since the
  // kernel should answer immediately.
  bool GetAddresses(int interface_index,
                    uint8_t unwanted_flags,
                    std::vector<AddressInfo>* addresses,
                    int* num_ipv6_nodad_dadfailed_addresses) override;

  // Performs the given verb that modifies local addresses on the given
  // interface_index.
  //
  // additional_attributes are RTAs (man 7 rtnelink) that will be sent together
  // with the netlink message. Note that rta_len in each RTA is used to decide
  // the length of the payload. The caller is responsible for making sure
  // payload bytes are accessible after the RTA header.
  bool ChangeLocalAddress(
      uint32_t interface_index,
      Verb verb,
      const QuicIpAddress& address,
      uint8_t prefix_length,
      uint8_t ifa_flags,
      uint8_t ifa_scope,
      const std::vector<struct rtattr*>& additional_attributes) override;

  // Gets the list of routing rules from the main routing table (RT_TABLE_MAIN),
  // which is programmable.
  //
  // This is a synchronous communication. This should not be a problem since the
  // kernel should answer immediately.
  bool GetRouteInfo(std::vector<RoutingRule>* routing_rules) override;

  // Performs the given Verb on the matching rule in the main routing table
  // (RT_TABLE_MAIN).
  //
  // preferred_source can be !IsInitialized(), in which case it will be omitted.
  //
  // For Verb::kRemove, rule matching is done by (destination_subnet, scope,
  // preferred_source, interface_index). Return true if a matching rule is
  // found. interface_index can be 0 for wilecard.
  //
  // For Verb::kAdd, rule matching is done by destination_subnet. If a rule for
  // the given destination_subnet already exists, nothing will happen and false
  // is returned.
  //
  // For Verb::kReplace, rule matching is done by destination_subnet. If no
  // matching rule is found, a new entry will be created.
  bool ChangeRoute(Netlink::Verb verb,
                   uint32_t table,
                   const IpRange& destination_subnet,
                   uint8_t scope,
                   QuicIpAddress preferred_source,
                   int32_t interface_index) override;

  // Returns the set of all rules in the routing policy database.
  bool GetRuleInfo(std::vector<Netlink::IpRule>* ip_rules) override;

  // Performs the give verb on the matching rule in the routing policy database.
  // When deleting a rule, the |source_range| may be unspecified, in which case
  // the lowest priority rule from |table| will be removed. When adding a rule,
  // the |source_address| must be specified.
  bool ChangeRule(Verb verb, uint32_t table, IpRange source_range) override;

  // Sends a netlink message to the kernel. iov and iovlen represents an array
  // of struct iovec to be fed into sendmsg. The caller needs to make sure the
  // message conform to what's expected by NLMSG_* macros.
  //
  // This can be useful if more flexibility is needed than the provided
  // convenient methods can provide.
  bool Send(struct iovec* iov, size_t iovlen) override;

  // Receives a netlink message from the kernel.
  // parser will be called on the caller's stack.
  //
  // This can be useful if more flexibility is needed than the provided
  // convenient methods can provide.
  // TODO(b/69412655): vectorize this.
  bool Recv(uint32_t seq, NetlinkParserInterface* parser) override;

 private:
  // Reset the size of recvbuf_ to size. If size is 0, recvbuf_ will be nullptr.
  void ResetRecvBuf(size_t size);

  // Opens a netlink socket if not already opened.
  bool OpenSocket();

  // Closes the opened netlink socket. Noop if no netlink socket is opened.
  void CloseSocket();

  KernelInterface* kernel_;
  int socket_fd_ = -1;
  std::unique_ptr<char[]> recvbuf_ = nullptr;
  size_t recvbuf_length_ = 0;
  uint32_t seq_;  // next msg sequence number
};

}  // namespace quic

#endif  // QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_