blob: d34f547b73bcfb7ff6b0cf9ceb9981f052491e06 [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,
Paul Stewarte00600e2012-03-16 07:08:00 -070026 Technology::Identifier technology,
Paul Stewart9a908082011-08-31 12:18:48 -070027 const DeviceInfo *device_info)
Paul Stewartdd60e452011-08-08 11:38:36 -070028 : is_default_(false),
Paul Stewartc8f4bef2011-12-13 09:45:51 -080029 routing_request_count_(0),
Paul Stewartdd60e452011-08-08 11:38:36 -070030 interface_index_(interface_index),
31 interface_name_(interface_name),
Paul Stewarte00600e2012-03-16 07:08:00 -070032 technology_(technology),
Paul Stewart9a908082011-08-31 12:18:48 -070033 device_info_(device_info),
Paul Stewartdd60e452011-08-08 11:38:36 -070034 resolver_(Resolver::GetInstance()),
35 routing_table_(RoutingTable::GetInstance()),
36 rtnl_handler_(RTNLHandler::GetInstance()) {
37 VLOG(2) << __func__;
38}
39
40Connection::~Connection() {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080041 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewart9a908082011-08-31 12:18:48 -070042
Paul Stewartc8f4bef2011-12-13 09:45:51 -080043 DCHECK(!routing_request_count_);
Thieu Lefb46caf2012-03-08 11:57:15 -080044 routing_table_->FlushRoutes(interface_index_);
Paul Stewart9a908082011-08-31 12:18:48 -070045 device_info_->FlushAddresses(interface_index_);
Paul Stewartdd60e452011-08-08 11:38:36 -070046}
47
48void Connection::UpdateFromIPConfig(const IPConfigRefPtr &config) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080049 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewarte6132022011-08-16 09:11:02 -070050
Paul Stewart9a908082011-08-31 12:18:48 -070051 const IPConfig::Properties &properties = config->properties();
52 IPAddress local(properties.address_family);
53 if (!local.SetAddressFromString(properties.address)) {
54 LOG(ERROR) << "Local address " << properties.address << " is invalid";
55 return;
56 }
57 local.set_prefix(properties.subnet_cidr);
58
59 IPAddress broadcast(properties.address_family);
Paul Stewarte00600e2012-03-16 07:08:00 -070060 if (!broadcast.SetAddressFromString(properties.broadcast_address) &&
61 technology_ != Technology::kTunnel) {
Paul Stewart9a908082011-08-31 12:18:48 -070062 LOG(ERROR) << "Broadcast address " << properties.broadcast_address
63 << " is invalid";
64 return;
65 }
66
67 rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
Paul Stewartdd60e452011-08-08 11:38:36 -070068
Paul Stewart7cfca042011-12-08 14:18:17 -080069 routing_table_->SetDefaultRoute(interface_index_, config,
70 GetMetric(is_default_));
Paul Stewartdd60e452011-08-08 11:38:36 -070071
Paul Stewart3f68bb12012-03-15 13:33:10 -070072 // Install any explicitly configured routes at the default metric.
73 routing_table_->ConfigureRoutes(interface_index_, config, kDefaultMetric);
74
Paul Stewartdd60e452011-08-08 11:38:36 -070075 // Save a copy of the last non-null DNS config
76 if (!config->properties().dns_servers.empty()) {
77 dns_servers_ = config->properties().dns_servers;
78 dns_domain_search_ = config->properties().domain_search;
79 }
80
81 if (is_default_) {
82 resolver_->SetDNSFromIPConfig(config);
83 }
84}
85
Paul Stewartc1dec4d2011-12-08 15:25:28 -080086void Connection::SetIsDefault(bool is_default) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080087 VLOG(2) << __func__ << " "
88 << interface_name_ << " (index " << interface_index_ << ") "
89 << is_default_ << " -> " << is_default;
Paul Stewartdd60e452011-08-08 11:38:36 -070090 if (is_default == is_default_) {
91 return;
92 }
93
Paul Stewart7cfca042011-12-08 14:18:17 -080094 routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
Paul Stewartdd60e452011-08-08 11:38:36 -070095
Paul Stewartc681fa02012-03-02 19:40:04 -080096 is_default_ = is_default;
97
Paul Stewartdd60e452011-08-08 11:38:36 -070098 if (is_default) {
99 resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
Paul Stewartc681fa02012-03-02 19:40:04 -0800100 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
101 if (device) {
102 device->RequestPortalDetection();
103 }
Paul Stewartdd60e452011-08-08 11:38:36 -0700104 }
Paul Stewartdd60e452011-08-08 11:38:36 -0700105}
106
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800107void Connection::RequestRouting() {
108 if (routing_request_count_++ == 0) {
109 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
110 DCHECK(device.get());
111 if (!device.get()) {
112 LOG(ERROR) << "Device is NULL!";
113 return;
114 }
115 device->DisableReversePathFilter();
116 }
117}
118
119void Connection::ReleaseRouting() {
120 DCHECK(routing_request_count_ > 0);
121 if (--routing_request_count_ == 0) {
122 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
123 DCHECK(device.get());
124 if (!device.get()) {
125 LOG(ERROR) << "Device is NULL!";
126 return;
127 }
128 device->EnableReversePathFilter();
129
130 // Clear any cached routes that might have accumulated while reverse-path
131 // filtering was disabled.
132 routing_table_->FlushCache();
133 }
134}
135
Paul Stewartf748a362012-03-07 12:01:20 -0800136bool Connection::RequestHostRoute(const IPAddress &address) {
137 // Set the prefix to be the entire address size.
138 IPAddress address_prefix(address);
139 address_prefix.set_prefix(address_prefix.GetLength() * 8);
140
141 if (!routing_table_->RequestRouteToHost(address_prefix, interface_index_)) {
142 LOG(ERROR) << "Could not request route to " << address.ToString();
143 return false;
144 }
145
146 return true;
147}
148
Paul Stewart7cfca042011-12-08 14:18:17 -0800149uint32 Connection::GetMetric(bool is_default) {
150 // If this is not the default route, assign a metric based on the interface
151 // index. This way all non-default routes (even to the same gateway IP) end
152 // up with unique metrics so they do not collide.
153 return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
154}
155
Paul Stewartdd60e452011-08-08 11:38:36 -0700156} // namespace shill