routing_table.cc revision 9a908080fc2a72dbf06f995b878fc8a3693b725a
175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart// Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart// Use of this source code is governed by a BSD-style license that can be 375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart// found in the LICENSE file. 475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/routing_table.h" 675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <arpa/inet.h> 875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <fcntl.h> 975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <linux/netlink.h> 1075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <linux/rtnetlink.h> 1175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <netinet/ether.h> 1275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <net/if.h> 1375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <net/if_arp.h> 1475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <string.h> 1575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <sys/socket.h> 1675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <time.h> 1775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <unistd.h> 1875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 1975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <string> 2075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 2175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/callback_old.h> 2275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/file_path.h> 2375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/file_util.h> 2475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/hash_tables.h> 2575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/logging.h> 2675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/memory/scoped_ptr.h> 2775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/stl_util-inl.h> 2875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include <base/stringprintf.h> 2975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 3075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/byte_string.h" 3175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/routing_table_entry.h" 3275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/rtnl_handler.h" 3375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/rtnl_listener.h" 3475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart#include "shill/rtnl_message.h" 3575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 3675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartusing std::string; 3775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartusing std::vector; 3875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 3975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartnamespace shill { 4075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 410d2ada3971075e78fb9900d0753c9ad94c15add4Paul Stewartstatic base::LazyInstance<RoutingTable> g_routing_table( 420d2ada3971075e78fb9900d0753c9ad94c15add4Paul Stewart base::LINKER_INITIALIZED); 430d2ada3971075e78fb9900d0753c9ad94c15add4Paul Stewart 4475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart// static 4575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartconst char RoutingTable::kRouteFlushPath4[] = "/proc/sys/net/ipv4/route/flush"; 460d2ada3971075e78fb9900d0753c9ad94c15add4Paul Stewart// static 4775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartconst char RoutingTable::kRouteFlushPath6[] = "/proc/sys/net/ipv6/route/flush"; 4875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 4975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul StewartRoutingTable::RoutingTable() 5075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart : route_callback_(NewCallback(this, &RoutingTable::RouteMsgHandler)), 5175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_listener_(NULL) { 5275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 5375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 5475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 5575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul StewartRoutingTable::~RoutingTable() {} 5675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 5775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul StewartRoutingTable* RoutingTable::GetInstance() { 580d2ada3971075e78fb9900d0753c9ad94c15add4Paul Stewart return g_routing_table.Pointer(); 5975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 6075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 6175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartvoid RoutingTable::Start() { 6275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 6375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 6475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_listener_.reset( 6575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart new RTNLListener(RTNLHandler::kRequestRoute, route_callback_.get())); 6675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RTNLHandler::GetInstance()->RequestDump( 679a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLHandler::kRequestRoute); 6875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 6975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 7075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartvoid RoutingTable::Stop() { 7175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 7275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 7375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_listener_.reset(); 7475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 7575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 7675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartbool RoutingTable::AddRoute(int interface_index, 7775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart const RoutingTableEntry &entry) { 7875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 7975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 8075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart CHECK(!entry.from_rtnl); 8175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (!ApplyRoute(interface_index, 8275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry, 839a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLMessage::kModeAdd, 8475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart NLM_F_CREATE | NLM_F_EXCL)) { 8575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return false; 8675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 8775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart tables_[interface_index].push_back(entry); 8875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return true; 8975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 9075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 9175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartbool RoutingTable::GetDefaultRoute(int interface_index, 9275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart IPAddress::Family family, 9375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RoutingTableEntry *entry) { 9475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 9575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 9675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart base::hash_map<int, vector<RoutingTableEntry> >::iterator table = 9775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart tables_.find(interface_index); 9875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 9975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (table == tables_.end()) { 10075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return false; 10175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 10275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 10375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart vector<RoutingTableEntry>::iterator nent; 10475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 10575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart for (nent = table->second.begin(); nent != table->second.end(); ++nent) { 10675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (nent->dst.IsDefault() && nent->dst.family() == family) { 10775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart *entry = *nent; 10875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return true; 10975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 11075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 11175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 11275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return false; 11375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 11475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 11575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartbool RoutingTable::SetDefaultRoute(int interface_index, 11675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart const IPConfigRefPtr &ipconfig, 11775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart uint32 metric) { 11875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart const IPConfig::Properties &ipconfig_props = ipconfig->properties(); 11975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RoutingTableEntry old_entry; 12075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 12175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 12275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 12375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart IPAddress gateway_address(ipconfig_props.address_family); 12475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (!gateway_address.SetAddressFromString(ipconfig_props.gateway)) { 12575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return false; 12675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 12775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 12875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (GetDefaultRoute(interface_index, 12975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ipconfig_props.address_family, 13075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart &old_entry)) { 13175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (old_entry.gateway.Equals(gateway_address)) { 13275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (old_entry.metric != metric) { 13375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart old_entry.metric = metric; 1349a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart ApplyRoute(interface_index, old_entry, RTNLMessage::kModeAdd, 13575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart NLM_F_CREATE | NLM_F_REPLACE); 13675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 13775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return true; 13875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } else { 13975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ApplyRoute(interface_index, 14075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart old_entry, 1419a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLMessage::kModeDelete, 14275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 0); 14375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 14475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 14575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 14675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart IPAddress default_address(ipconfig_props.address_family); 14775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart default_address.SetAddressToDefault(); 14875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 14975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return AddRoute(interface_index, 15075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RoutingTableEntry(default_address, 15175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart default_address, 15275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart gateway_address, 15375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart metric, 15475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RT_SCOPE_UNIVERSE, 15575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart false)); 15675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 15775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 15875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartvoid RoutingTable::FlushRoutes(int interface_index) { 15975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 16075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 16175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart base::hash_map<int, vector<RoutingTableEntry> >::iterator table = 16275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart tables_.find(interface_index); 16375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 16475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (table == tables_.end()) { 16575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return; 16675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 16775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 16875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart vector<RoutingTableEntry>::iterator nent; 16975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 17075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart for (nent = table->second.begin(); nent != table->second.end(); ++nent) { 1719a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart ApplyRoute(interface_index, *nent, RTNLMessage::kModeDelete, 0); 17275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 17375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 17475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 17575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartvoid RoutingTable::ResetTable(int interface_index) { 17675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart tables_.erase(interface_index); 17775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 17875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 17975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartvoid RoutingTable::SetDefaultMetric(int interface_index, uint32 metric) { 18075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RoutingTableEntry entry; 18175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 18275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 18375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 18475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (GetDefaultRoute(interface_index, IPAddress::kAddressFamilyIPv4, &entry) && 18575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.metric != metric) { 18675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.metric = metric; 1879a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart ApplyRoute(interface_index, entry, RTNLMessage::kModeAdd, 18875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart NLM_F_CREATE | NLM_F_REPLACE); 18975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 19075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 19175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (GetDefaultRoute(interface_index, IPAddress::kAddressFamilyIPv6, &entry) && 19275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.metric != metric) { 19375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.metric = metric; 1949a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart ApplyRoute(interface_index, entry, RTNLMessage::kModeAdd, 19575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart NLM_F_CREATE | NLM_F_REPLACE); 19675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 19775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 19875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 1992aa9707f114ab8166f45df5726bf05278df2aef6Chris Masonevoid RoutingTable::RouteMsgHandler(const RTNLMessage &msg) { 20075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 20175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 2029a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.type() != RTNLMessage::kTypeRoute || 20375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.family() == IPAddress::kAddressFamilyUnknown || 20475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart !msg.HasAttribute(RTA_OIF)) { 20575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return; 20675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 20775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 20875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart const RTNLMessage::RouteStatus &route_status = msg.route_status(); 20975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 21075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (route_status.type != RTN_UNICAST || 21175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_status.protocol != RTPROT_BOOT || 21275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_status.table != RT_TABLE_MAIN) { 21375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return; 21475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 21575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 21675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart uint32 interface_index = 0; 21775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (!msg.GetAttribute(RTA_OIF).ConvertToCPUUInt32(&interface_index)) { 21875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return; 21975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 22075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 22175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart uint32 metric = 0; 22275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (msg.HasAttribute(RTA_PRIORITY)) { 22375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&metric); 22475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 22575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 22675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart IPAddress default_addr(msg.family()); 22775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart default_addr.SetAddressToDefault(); 22875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 22975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ByteString dst_bytes(default_addr.address()); 23075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (msg.HasAttribute(RTA_DST)) { 23175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart dst_bytes = msg.GetAttribute(RTA_DST); 23275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 23375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ByteString src_bytes(default_addr.address()); 23475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (msg.HasAttribute(RTA_SRC)) { 23575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart src_bytes = msg.GetAttribute(RTA_SRC); 23675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 23775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ByteString gateway_bytes(default_addr.address()); 23875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (msg.HasAttribute(RTA_GATEWAY)) { 23975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart gateway_bytes = msg.GetAttribute(RTA_GATEWAY); 24075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 24175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 24275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RoutingTableEntry entry( 2439e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart IPAddress(msg.family(), dst_bytes, route_status.dst_prefix), 2449e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart IPAddress(msg.family(), src_bytes, route_status.src_prefix), 24575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart IPAddress(msg.family(), gateway_bytes), 24675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart metric, 24775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart route_status.scope, 24875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart true); 24975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 25075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart vector<RoutingTableEntry> &table = tables_[interface_index]; 25175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart vector<RoutingTableEntry>::iterator nent; 25275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart for (nent = table.begin(); nent != table.end(); ++nent) { 25375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (nent->dst.Equals(entry.dst) && 25475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart nent->src.Equals(entry.src) && 25575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart nent->gateway.Equals(entry.gateway) && 25675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart nent->scope == entry.scope) { 2579a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeDelete) { 25875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart table.erase(nent); 25975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } else { 26075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart nent->from_rtnl = true; 26175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart nent->metric = entry.metric; 26275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 26375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return; 26475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 26575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 26675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 2679a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (msg.mode() == RTNLMessage::kModeAdd) { 26875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart table.push_back(entry); 26975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 27075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 27175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 27275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartbool RoutingTable::ApplyRoute(uint32 interface_index, 27375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart const RoutingTableEntry &entry, 2749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLMessage::Mode mode, 27575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart unsigned int flags) { 27675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << base::StringPrintf("%s: index %d mode %d flags 0x%x", 27775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart __func__, interface_index, mode, flags); 27875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 27975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RTNLMessage msg( 2809a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart RTNLMessage::kTypeRoute, 28175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart mode, 282e613202d36e3bfb06a40eea1888694413210ef7ePaul Stewart NLM_F_REQUEST | flags, 28375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 0, 28475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 0, 28575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 0, 28675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.dst.family()); 28775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 28875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.set_route_status(RTNLMessage::RouteStatus( 2899e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart entry.dst.prefix(), 2909e3fcd7141240bc5efd0bf1513b9e78aa79d90ebPaul Stewart entry.src.prefix(), 29175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RT_TABLE_MAIN, 29275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RTPROT_BOOT, 29375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart entry.scope, 29475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart RTN_UNICAST, 29575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 0)); 29675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 29775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.SetAttribute(RTA_DST, entry.dst.address()); 29875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (!entry.src.IsDefault()) { 29975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.SetAttribute(RTA_SRC, entry.src.address()); 30075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 30175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (!entry.gateway.IsDefault()) { 30275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.SetAttribute(RTA_GATEWAY, entry.gateway.address()); 30375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 30475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric)); 30575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index)); 30675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 30775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return RTNLHandler::GetInstance()->SendMessage(&msg); 30875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 30975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 31075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewartbool RoutingTable::FlushCache() { 31175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart static const char *kPaths[2] = { kRouteFlushPath4, kRouteFlushPath6 }; 31275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart bool ret = true; 31375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 31475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart VLOG(2) << __func__; 31575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 31675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart for (size_t i = 0; i < arraysize(kPaths); ++i) { 31775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart if (file_util::WriteFile(FilePath(kPaths[i]), "-1", 2) != 2) { 31875e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart LOG(ERROR) << base::StringPrintf("Cannot write to route flush file %s", 31975e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart kPaths[i]); 32075e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart ret = false; 32175e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 32275e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart } 32375e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 32475e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart return ret; 32575e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} 32675e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart 32775e89d2d5ecb3c42a869f485d4483fd2176381c0Paul Stewart} // namespace shill 328