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