xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_
6 #define QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_
7 
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
10 
11 #include <cstdint>
12 #include <functional>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "quiche/quic/platform/api/quic_ip_address.h"
18 #include "quiche/quic/qbone/platform/ip_range.h"
19 #include "quiche/quic/qbone/platform/kernel_interface.h"
20 #include "quiche/quic/qbone/platform/netlink_interface.h"
21 
22 namespace quic {
23 
24 // A wrapper class to provide convenient methods of manipulating IP address and
25 // routing table using netlink (man 7 netlink) socket. More specifically,
26 // rtnetlink is used (man 7 rtnetlink).
27 //
28 // This class is not thread safe, but thread compatible, as long as callers can
29 // make sure Send and Recv pairs are executed in sequence for a particular
30 // query.
31 class Netlink : public NetlinkInterface {
32  public:
33   explicit Netlink(KernelInterface* kernel);
34   ~Netlink() override;
35 
36   // Gets the link information for the interface referred by the given
37   // interface_name.
38   //
39   // This is a synchronous communication. That should not be a problem since the
40   // kernel should answer immediately.
41   bool GetLinkInfo(const std::string& interface_name,
42                    LinkInfo* link_info) override;
43 
44   // Gets the addresses for the given interface referred by the given
45   // interface_index.
46   //
47   // This is a synchronous communication. This should not be a problem since the
48   // kernel should answer immediately.
49   bool GetAddresses(int interface_index, uint8_t unwanted_flags,
50                     std::vector<AddressInfo>* addresses,
51                     int* num_ipv6_nodad_dadfailed_addresses) override;
52 
53   // Performs the given verb that modifies local addresses on the given
54   // interface_index.
55   //
56   // additional_attributes are RTAs (man 7 rtnelink) that will be sent together
57   // with the netlink message. Note that rta_len in each RTA is used to decide
58   // the length of the payload. The caller is responsible for making sure
59   // payload bytes are accessible after the RTA header.
60   bool ChangeLocalAddress(
61       uint32_t interface_index, Verb verb, const QuicIpAddress& address,
62       uint8_t prefix_length, uint8_t ifa_flags, uint8_t ifa_scope,
63       const std::vector<struct rtattr*>& additional_attributes) override;
64 
65   // Gets the list of routing rules from the main routing table (RT_TABLE_MAIN),
66   // which is programmable.
67   //
68   // This is a synchronous communication. This should not be a problem since the
69   // kernel should answer immediately.
70   bool GetRouteInfo(std::vector<RoutingRule>* routing_rules) override;
71 
72   // Performs the given Verb on the matching rule in the main routing table
73   // (RT_TABLE_MAIN).
74   //
75   // preferred_source can be !IsInitialized(), in which case it will be omitted.
76   //
77   // init_cwnd will be left unspecified if set to 0.
78   //
79   // For Verb::kRemove, rule matching is done by (destination_subnet, scope,
80   // preferred_source, interface_index). Return true if a matching rule is
81   // found. interface_index can be 0 for wilecard.
82   //
83   // For Verb::kAdd, rule matching is done by destination_subnet. If a rule for
84   // the given destination_subnet already exists, nothing will happen and false
85   // is returned.
86   //
87   // For Verb::kReplace, rule matching is done by destination_subnet. If no
88   // matching rule is found, a new entry will be created.
89   bool ChangeRoute(Netlink::Verb verb, uint32_t table,
90                    const IpRange& destination_subnet, uint8_t scope,
91                    QuicIpAddress preferred_source, int32_t interface_index,
92                    uint32_t init_cwnd) override;
93 
94   // Returns the set of all rules in the routing policy database.
95   bool GetRuleInfo(std::vector<Netlink::IpRule>* ip_rules) override;
96 
97   // Performs the give verb on the matching rule in the routing policy database.
98   // When deleting a rule, the |source_range| may be unspecified, in which case
99   // the lowest priority rule from |table| will be removed. When adding a rule,
100   // the |source_address| must be specified.
101   bool ChangeRule(Verb verb, uint32_t table, IpRange source_range) override;
102 
103   // Sends a netlink message to the kernel. iov and iovlen represents an array
104   // of struct iovec to be fed into sendmsg. The caller needs to make sure the
105   // message conform to what's expected by NLMSG_* macros.
106   //
107   // This can be useful if more flexibility is needed than the provided
108   // convenient methods can provide.
109   bool Send(struct iovec* iov, size_t iovlen) override;
110 
111   // Receives a netlink message from the kernel.
112   // parser will be called on the caller's stack.
113   //
114   // This can be useful if more flexibility is needed than the provided
115   // convenient methods can provide.
116   // TODO(b/69412655): vectorize this.
117   bool Recv(uint32_t seq, NetlinkParserInterface* parser) override;
118 
119  private:
120   // Reset the size of recvbuf_ to size. If size is 0, recvbuf_ will be nullptr.
121   void ResetRecvBuf(size_t size);
122 
123   // Opens a netlink socket if not already opened.
124   bool OpenSocket();
125 
126   // Closes the opened netlink socket. Noop if no netlink socket is opened.
127   void CloseSocket();
128 
129   KernelInterface* kernel_;
130   int socket_fd_ = -1;
131   std::unique_ptr<char[]> recvbuf_ = nullptr;
132   size_t recvbuf_length_ = 0;
133   uint32_t seq_;  // next msg sequence number
134 };
135 
136 }  // namespace quic
137 
138 #endif  // QUICHE_QUIC_QBONE_PLATFORM_NETLINK_H_
139