blob: cab4bd216b796516579af06226dfc8c54c9d80e3 [file] [log] [blame]
mukesh agrawalddc378f2012-02-17 18:26:20 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartdd60e452011-08-08 11:38:36 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/connection.h"
6
Paul Stewart9a908082011-08-31 12:18:48 -07007#include <arpa/inet.h>
8#include <linux/rtnetlink.h>
9
10#include "shill/device_info.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070011#include "shill/resolver.h"
12#include "shill/routing_table.h"
13#include "shill/rtnl_handler.h"
14
15using std::string;
16
17namespace shill {
18
19// static
20const uint32 Connection::kDefaultMetric = 1;
21// static
Paul Stewart7cfca042011-12-08 14:18:17 -080022const uint32 Connection::kNonDefaultMetricBase = 10;
Paul Stewartdd60e452011-08-08 11:38:36 -070023
Paul Stewart9a908082011-08-31 12:18:48 -070024Connection::Connection(int interface_index,
25 const std::string& interface_name,
26 const DeviceInfo *device_info)
Paul Stewartdd60e452011-08-08 11:38:36 -070027 : is_default_(false),
Paul Stewartc8f4bef2011-12-13 09:45:51 -080028 routing_request_count_(0),
Paul Stewartdd60e452011-08-08 11:38:36 -070029 interface_index_(interface_index),
30 interface_name_(interface_name),
Paul Stewart9a908082011-08-31 12:18:48 -070031 device_info_(device_info),
Paul Stewartdd60e452011-08-08 11:38:36 -070032 resolver_(Resolver::GetInstance()),
33 routing_table_(RoutingTable::GetInstance()),
34 rtnl_handler_(RTNLHandler::GetInstance()) {
35 VLOG(2) << __func__;
36}
37
38Connection::~Connection() {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080039 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewart9a908082011-08-31 12:18:48 -070040
Paul Stewartc8f4bef2011-12-13 09:45:51 -080041 DCHECK(!routing_request_count_);
Thieu Lefb46caf2012-03-08 11:57:15 -080042 routing_table_->FlushRoutes(interface_index_);
Paul Stewart9a908082011-08-31 12:18:48 -070043 device_info_->FlushAddresses(interface_index_);
Paul Stewartdd60e452011-08-08 11:38:36 -070044}
45
46void Connection::UpdateFromIPConfig(const IPConfigRefPtr &config) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080047 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewarte6132022011-08-16 09:11:02 -070048
Paul Stewart9a908082011-08-31 12:18:48 -070049 const IPConfig::Properties &properties = config->properties();
50 IPAddress local(properties.address_family);
51 if (!local.SetAddressFromString(properties.address)) {
52 LOG(ERROR) << "Local address " << properties.address << " is invalid";
53 return;
54 }
55 local.set_prefix(properties.subnet_cidr);
56
57 IPAddress broadcast(properties.address_family);
58 if (!broadcast.SetAddressFromString(properties.broadcast_address)) {
59 LOG(ERROR) << "Broadcast address " << properties.broadcast_address
60 << " is invalid";
61 return;
62 }
63
64 rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
Paul Stewartdd60e452011-08-08 11:38:36 -070065
Paul Stewart7cfca042011-12-08 14:18:17 -080066 routing_table_->SetDefaultRoute(interface_index_, config,
67 GetMetric(is_default_));
Paul Stewartdd60e452011-08-08 11:38:36 -070068
Paul Stewart3f68bb12012-03-15 13:33:10 -070069 // Install any explicitly configured routes at the default metric.
70 routing_table_->ConfigureRoutes(interface_index_, config, kDefaultMetric);
71
Paul Stewartdd60e452011-08-08 11:38:36 -070072 // Save a copy of the last non-null DNS config
73 if (!config->properties().dns_servers.empty()) {
74 dns_servers_ = config->properties().dns_servers;
75 dns_domain_search_ = config->properties().domain_search;
76 }
77
78 if (is_default_) {
79 resolver_->SetDNSFromIPConfig(config);
80 }
81}
82
Paul Stewartc1dec4d2011-12-08 15:25:28 -080083void Connection::SetIsDefault(bool is_default) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080084 VLOG(2) << __func__ << " "
85 << interface_name_ << " (index " << interface_index_ << ") "
86 << is_default_ << " -> " << is_default;
Paul Stewartdd60e452011-08-08 11:38:36 -070087 if (is_default == is_default_) {
88 return;
89 }
90
Paul Stewart7cfca042011-12-08 14:18:17 -080091 routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
Paul Stewartdd60e452011-08-08 11:38:36 -070092
Paul Stewartc681fa02012-03-02 19:40:04 -080093 is_default_ = is_default;
94
Paul Stewartdd60e452011-08-08 11:38:36 -070095 if (is_default) {
96 resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
Paul Stewartc681fa02012-03-02 19:40:04 -080097 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
98 if (device) {
99 device->RequestPortalDetection();
100 }
Paul Stewartdd60e452011-08-08 11:38:36 -0700101 }
Paul Stewartdd60e452011-08-08 11:38:36 -0700102}
103
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800104void Connection::RequestRouting() {
105 if (routing_request_count_++ == 0) {
106 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
107 DCHECK(device.get());
108 if (!device.get()) {
109 LOG(ERROR) << "Device is NULL!";
110 return;
111 }
112 device->DisableReversePathFilter();
113 }
114}
115
116void Connection::ReleaseRouting() {
117 DCHECK(routing_request_count_ > 0);
118 if (--routing_request_count_ == 0) {
119 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
120 DCHECK(device.get());
121 if (!device.get()) {
122 LOG(ERROR) << "Device is NULL!";
123 return;
124 }
125 device->EnableReversePathFilter();
126
127 // Clear any cached routes that might have accumulated while reverse-path
128 // filtering was disabled.
129 routing_table_->FlushCache();
130 }
131}
132
Paul Stewartf748a362012-03-07 12:01:20 -0800133bool Connection::RequestHostRoute(const IPAddress &address) {
134 // Set the prefix to be the entire address size.
135 IPAddress address_prefix(address);
136 address_prefix.set_prefix(address_prefix.GetLength() * 8);
137
138 if (!routing_table_->RequestRouteToHost(address_prefix, interface_index_)) {
139 LOG(ERROR) << "Could not request route to " << address.ToString();
140 return false;
141 }
142
143 return true;
144}
145
Paul Stewart7cfca042011-12-08 14:18:17 -0800146uint32 Connection::GetMetric(bool is_default) {
147 // If this is not the default route, assign a metric based on the interface
148 // index. This way all non-default routes (even to the same gateway IP) end
149 // up with unique metrics so they do not collide.
150 return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
151}
152
Paul Stewartdd60e452011-08-08 11:38:36 -0700153} // namespace shill