text: // 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 "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
  #include "net/third_party/quiche/src/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 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_
  