| // Copyright 2019 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef PATCHPANEL_NETWORK_ROUTING_TABLE_H_ | |
| #define PATCHPANEL_NETWORK_ROUTING_TABLE_H_ | |
| #include <memory> | |
| #include <set> | |
| #include <string> | |
| #include <unordered_map> | |
| #include <vector> | |
| #include <base/functional/callback.h> | |
| #include <base/lazy_instance.h> | |
| #include <base/logging.h> | |
| #include <base/memory/ref_counted.h> | |
| #include <chromeos/net-base/ip_address.h> | |
| #include <chromeos/net-base/rtnl_handler.h> | |
| #include <chromeos/net-base/rtnl_listener.h> | |
| #include <chromeos/net-base/rtnl_message.h> | |
| #include "patchpanel/network/routing_table_entry.h" | |
| namespace patchpanel { | |
| // This singleton maintains an in-process copy of the routing table on | |
| // a per-interface basis. It offers the ability for other modules to | |
| // make modifications to the routing table, centered around setting the | |
| // default route for an interface or modifying its metric (priority). | |
| class RoutingTable { | |
| public: | |
| // Used to detect default route added by kernel when receiving RA. | |
| // Note that since 5.18 kernel this value will become configurable through | |
| // net.ipv6.conf.all.ra_defrtr_metric and we need to be sure this value | |
| // remains identical with kernel configuration. | |
| static constexpr int kKernelSlaacRouteMetric = 1024; | |
| // The metric patchpanel will install its IPv4 default route. Does not have | |
| // real impact to the routing decision since there will only be one default | |
| // route in each routing table. | |
| static constexpr int kDefaultRouteMetric = 65536; | |
| // ID for the routing table that used for CLAT default routes. Patchpanel is | |
| // responsible for adding and removing routes in this table. Using a user | |
| // defined table ID lesser than 255 to avoid conflict with per-device table | |
| // (for which we use table ID 1000+). | |
| static constexpr uint32_t kClatRoutingTableId = 249; | |
| // ID for a routing table to block all traffic. Used in b/180521518 to prevent | |
| // Chrome to send traffic through IPv6 cellular when there is another | |
| // IPv4-only primary network. | |
| static constexpr uint32_t kUnreachableTableId = 250; | |
| RoutingTable(); | |
| RoutingTable(const RoutingTable&) = delete; | |
| RoutingTable& operator=(const RoutingTable&) = delete; | |
| virtual ~RoutingTable(); | |
| virtual void Start(); | |
| // Add an entry to the routing table. | |
| virtual bool AddRoute(int interface_index, const RoutingTableEntry& entry); | |
| // Remove an entry from the routing table. | |
| virtual bool RemoveRoute(int interface_index, const RoutingTableEntry& entry); | |
| // Set the default route for an interface with index |interface_index|, | |
| // given the IPAddress of the gateway |gateway_address| and priority | |
| // |metric|. | |
| virtual bool SetDefaultRoute(int interface_index, | |
| const net_base::IPAddress& gateway_address, | |
| uint32_t table_id); | |
| // Create a blackhole route for a given IP family. Returns true | |
| // on successfully sending the route request, false otherwise. | |
| virtual bool CreateBlackholeRoute(int interface_index, | |
| net_base::IPFamily family, | |
| uint32_t metric, | |
| uint32_t table_id); | |
| // Remove routes associated with interface. | |
| // Route entries are immediately purged from our copy of the routing table. | |
| virtual void FlushRoutes(int interface_index); | |
| // Iterate over all routing tables removing all routes added by patchpanel, | |
| // associated with interface |tag| , and of IP family |family|. Route entries | |
| // are immediately purged from our copy of the routing table. | |
| virtual void FlushRoutesWithTag(int tag, net_base::IPFamily family); | |
| // Reset local state for this interface. | |
| virtual void ResetTable(int interface_index); | |
| static uint32_t GetInterfaceTableId(int interface_index); | |
| private: | |
| friend base::LazyInstanceTraitsBase<RoutingTable>; | |
| friend class RoutingTableTest; | |
| using RouteTableEntryVector = std::vector<RoutingTableEntry>; | |
| using RouteTables = std::unordered_map<int, RouteTableEntryVector>; | |
| // Add an entry to the kernel routing table without modifying the internal | |
| // routing-table bookkeeping. | |
| bool AddRouteToKernelTable(int interface_index, | |
| const RoutingTableEntry& entry); | |
| // Remove an entry to the kernel routing table without modifying the internal | |
| // routing-table bookkeeping. | |
| bool RemoveRouteFromKernelTable(int interface_index, | |
| const RoutingTableEntry& entry); | |
| bool ApplyRoute(int interface_index, | |
| const RoutingTableEntry& entry, | |
| net_base::RTNLMessage::Mode mode, | |
| unsigned int flags); | |
| // Get the default route associated with an interface of a given addr family. | |
| // A pointer to the route is placed in |*entry|. | |
| virtual bool GetDefaultRouteInternal(int interface_index, | |
| net_base::IPFamily family, | |
| RoutingTableEntry** entry); | |
| RouteTables tables_; | |
| // Cache singleton pointer for performance and test purposes. | |
| net_base::RTNLHandler* rtnl_handler_; | |
| }; | |
| } // namespace patchpanel | |
| #endif // PATCHPANEL_NETWORK_ROUTING_TABLE_H_ |