| // 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_INTERFACE_H_ | 
 | #define QUICHE_QUIC_QBONE_PLATFORM_NETLINK_INTERFACE_H_ | 
 |  | 
 | #include <linux/rtnetlink.h> | 
 |  | 
 | #include "quic/platform/api/quic_ip_address.h" | 
 | #include "quic/qbone/platform/ip_range.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | constexpr int kHwAddrSize = 6; | 
 |  | 
 | class NetlinkParserInterface { | 
 |  public: | 
 |   virtual ~NetlinkParserInterface() {} | 
 |   virtual void Run(struct nlmsghdr* netlink_message) = 0; | 
 | }; | 
 |  | 
 | // An interface providing convenience methods for manipulating IP address and | 
 | // routing table using netlink (man 7 netlink) socket. | 
 | class NetlinkInterface { | 
 |  public: | 
 |   virtual ~NetlinkInterface() = default; | 
 |  | 
 |   // Link information returned from GetLinkInfo. | 
 |   struct LinkInfo { | 
 |     int index; | 
 |     uint8_t type; | 
 |     uint8_t hardware_address[kHwAddrSize]; | 
 |     uint8_t broadcast_address[kHwAddrSize]; | 
 |     size_t hardware_address_length;   // 0 if no hardware address found | 
 |     size_t broadcast_address_length;  // 0 if no broadcast address found | 
 |   }; | 
 |  | 
 |   // Gets the link information for the interface referred by the given | 
 |   // interface_name. | 
 |   virtual bool GetLinkInfo(const std::string& interface_name, | 
 |                            LinkInfo* link_info) = 0; | 
 |  | 
 |   // Address information reported back from GetAddresses. | 
 |   struct AddressInfo { | 
 |     QuicIpAddress local_address; | 
 |     QuicIpAddress interface_address; | 
 |     uint8_t prefix_length = 0; | 
 |     uint8_t scope = 0; | 
 |   }; | 
 |  | 
 |   // Gets the addresses for the given interface referred by the given | 
 |   // interface_index. | 
 |   virtual bool GetAddresses(int interface_index, | 
 |                             uint8_t unwanted_flags, | 
 |                             std::vector<AddressInfo>* addresses, | 
 |                             int* num_ipv6_nodad_dadfailed_addresses) = 0; | 
 |  | 
 |   enum class Verb { | 
 |     kAdd, | 
 |     kRemove, | 
 |     kReplace, | 
 |   }; | 
 |  | 
 |   // 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. | 
 |   virtual 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) = 0; | 
 |  | 
 |   // Routing rule reported back from GetRouteInfo. | 
 |   struct RoutingRule { | 
 |     uint32_t table; | 
 |     IpRange destination_subnet; | 
 |     QuicIpAddress preferred_source; | 
 |     uint8_t scope; | 
 |     int out_interface; | 
 |   }; | 
 |  | 
 |   struct IpRule { | 
 |     uint32_t table; | 
 |     IpRange source_range; | 
 |   }; | 
 |  | 
 |   // Gets the list of routing rules from the main routing table (RT_TABLE_MAIN), | 
 |   // which is programmable. | 
 |   virtual bool GetRouteInfo(std::vector<RoutingRule>* routing_rules) = 0; | 
 |  | 
 |   // 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. | 
 |   virtual bool ChangeRoute(Verb verb, | 
 |                            uint32_t table, | 
 |                            const IpRange& destination_subnet, | 
 |                            uint8_t scope, | 
 |                            QuicIpAddress preferred_source, | 
 |                            int32_t interface_index) = 0; | 
 |  | 
 |   // Returns the set of all rules in the routing policy database. | 
 |   virtual bool GetRuleInfo(std::vector<IpRule>* ip_rules) = 0; | 
 |  | 
 |   // 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. | 
 |   virtual bool ChangeRule(Verb verb, uint32_t table, IpRange source_range) = 0; | 
 |  | 
 |   // 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. | 
 |   virtual bool Send(struct iovec* iov, size_t iovlen) = 0; | 
 |  | 
 |   // 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. | 
 |   virtual bool Recv(uint32_t seq, NetlinkParserInterface* parser) = 0; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_QBONE_PLATFORM_NETLINK_INTERFACE_H_ |