blob: de211910610859b5010adaafeb751d60754d2501 [file] [log] [blame]
// Copyright (C) 2012 The Android Open Source Project
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
#include <deque>
#include <memory>
#include <unordered_map>
#include <vector>
#include <base/callback.h>
#include <base/lazy_instance.h>
#include <base/memory/ref_counted.h>
#include "shill/net/ip_address.h"
#include "shill/net/rtnl_message.h"
#include "shill/refptr_types.h"
namespace shill {
class RTNLHandler;
class RTNLListener;
struct RoutingPolicyEntry;
struct RoutingTableEntry;
// 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 {
using RouteTableEntryVector = std::vector<RoutingTableEntry>;
using RouteTables = std::unordered_map<int, RouteTableEntryVector>;
using PolicyTableEntryVector = std::vector<RoutingPolicyEntry>;
using PolicyTables = std::unordered_map<int, PolicyTableEntryVector>;
struct Query {
// Callback::Run(interface_index, entry)
using Callback = base::Callback<void(int, const RoutingTableEntry&)>;
Query() : sequence(0), tag(0), table_id(0) {}
Query(uint32_t sequence_in,
int tag_in,
Callback callback_in,
uint8_t table_id_in)
: sequence(sequence_in),
table_id(table_id_in) {}
uint32_t sequence;
int tag;
Callback callback;
uint8_t table_id;
virtual ~RoutingTable();
static RoutingTable* GetInstance();
virtual void Start();
virtual void Stop();
// Add an entry to the routing table.
virtual bool AddRoute(int interface_index, const RoutingTableEntry& entry);
// Add an entry to the routing rule table.
virtual bool AddRule(int interface_index, const RoutingPolicyEntry& entry);
// Get the default route associated with an interface of a given addr family.
// The route is copied into |*entry|.
virtual bool GetDefaultRoute(int interface_index,
IPAddress::Family family,
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 IPAddress& gateway_address,
uint32_t metric,
uint8_t table_id);
// Configure routing table entries from the "routes" portion of |ipconfig|.
// Returns true if all routes were installed successfully, false otherwise.
virtual bool ConfigureRoutes(int interface_index,
const IPConfigRefPtr& ipconfig,
uint32_t metric,
uint8_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,
IPAddress::Family family,
uint32_t metric,
uint8_t table_id);
// Create a route to a link-attached remote host. |remote_address|
// must be directly reachable from |local_address|. Returns true
// on successfully sending the route request, false otherwise.
virtual bool CreateLinkRoute(int interface_index,
const IPAddress& local_address,
const IPAddress& remote_address,
uint8_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 routes tagged with |tag|.
// Route entries are immediately purged from our copy of the routing table.
virtual void FlushRoutesWithTag(int tag);
// Flush the routing cache for all interfaces.
virtual bool FlushCache();
// Flush all routing rules for |interface_index|.
virtual void FlushRules(int interface_index);
// Reset local state for this interface.
virtual void ResetTable(int interface_index);
// Set the metric (priority) on existing default routes for an interface.
virtual void SetDefaultMetric(int interface_index, uint32_t metric);
// Get the default route to |destination| through |interface_index| and create
// a host route to that destination. When creating the route, tag our local
// entry with |tag|, so we can remove it later. Connections use their
// interface index as the tag, so that as they are destroyed, they can remove
// all their dependent routes. If |callback| is not null, it will be invoked
// when the request-route response is received and the add-route request has
// been sent successfully.
virtual bool RequestRouteToHost(const IPAddress& destination,
int interface_index,
int tag,
const Query::Callback& callback,
uint8_t table_id);
// Allocates a per-device routing table, and returns the ID. If no
// IDs are available, returns 0.
virtual unsigned char AllocTableId();
// Frees routing table |id| that was obtained from AllocTableId().
virtual void FreeTableId(unsigned char id);
friend struct base::DefaultLazyInstanceTraits<RoutingTable>;
friend class RoutingTableTest;
static bool ParseRoutingTableMessage(const RTNLMessage& message,
int* interface_index,
RoutingTableEntry* entry);
void RouteMsgHandler(const RTNLMessage& msg);
bool ApplyRoute(uint32_t interface_index,
const RoutingTableEntry& entry,
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,
IPAddress::Family family,
RoutingTableEntry** entry);
void ReplaceMetric(uint32_t interface_index,
RoutingTableEntry* entry,
uint32_t metric);
static const char kRouteFlushPath4[];
static const char kRouteFlushPath6[];
bool ApplyRule(uint32_t interface_index,
const RoutingPolicyEntry& entry,
RTNLMessage::Mode mode,
unsigned int flags);
bool ParseRoutingPolicyMessage(const RTNLMessage& message,
RoutingPolicyEntry* entry);
bool HandleRoutingPolicyMessage(const RTNLMessage& message);
RouteTables tables_;
PolicyTables policy_tables_;
std::unique_ptr<RTNLListener> route_listener_;
std::deque<Query> route_queries_;
// A list of unused routing table IDs.
std::vector<unsigned char> available_table_ids_;
// Cache singleton pointer for performance and test purposes.
RTNLHandler* rtnl_handler_;
} // namespace shill