blob: a69a690ca5877310d73d5e5bd557a37308abaea5 [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"
Paul Stewartf748a362012-03-07 12:01:20 -080013#include "shill/routing_table_entry.h"
Paul Stewartdd60e452011-08-08 11:38:36 -070014#include "shill/rtnl_handler.h"
15
16using std::string;
17
18namespace shill {
19
20// static
21const uint32 Connection::kDefaultMetric = 1;
22// static
Paul Stewart7cfca042011-12-08 14:18:17 -080023const uint32 Connection::kNonDefaultMetricBase = 10;
Paul Stewartdd60e452011-08-08 11:38:36 -070024
Paul Stewart9a908082011-08-31 12:18:48 -070025Connection::Connection(int interface_index,
26 const std::string& interface_name,
27 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 Stewart9a908082011-08-31 12:18:48 -070032 device_info_(device_info),
Paul Stewartdd60e452011-08-08 11:38:36 -070033 resolver_(Resolver::GetInstance()),
34 routing_table_(RoutingTable::GetInstance()),
35 rtnl_handler_(RTNLHandler::GetInstance()) {
36 VLOG(2) << __func__;
37}
38
39Connection::~Connection() {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080040 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewart9a908082011-08-31 12:18:48 -070041
Paul Stewartc8f4bef2011-12-13 09:45:51 -080042 DCHECK(!routing_request_count_);
Thieu Lefb46caf2012-03-08 11:57:15 -080043 routing_table_->FlushRoutes(interface_index_);
Paul Stewart9a908082011-08-31 12:18:48 -070044 device_info_->FlushAddresses(interface_index_);
Paul Stewartdd60e452011-08-08 11:38:36 -070045}
46
47void Connection::UpdateFromIPConfig(const IPConfigRefPtr &config) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080048 VLOG(2) << __func__ << " " << interface_name_;
Paul Stewarte6132022011-08-16 09:11:02 -070049
Paul Stewart9a908082011-08-31 12:18:48 -070050 const IPConfig::Properties &properties = config->properties();
51 IPAddress local(properties.address_family);
52 if (!local.SetAddressFromString(properties.address)) {
53 LOG(ERROR) << "Local address " << properties.address << " is invalid";
54 return;
55 }
56 local.set_prefix(properties.subnet_cidr);
57
58 IPAddress broadcast(properties.address_family);
59 if (!broadcast.SetAddressFromString(properties.broadcast_address)) {
60 LOG(ERROR) << "Broadcast address " << properties.broadcast_address
61 << " is invalid";
62 return;
63 }
64
65 rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
Paul Stewartdd60e452011-08-08 11:38:36 -070066
Paul Stewart7cfca042011-12-08 14:18:17 -080067 routing_table_->SetDefaultRoute(interface_index_, config,
68 GetMetric(is_default_));
Paul Stewartdd60e452011-08-08 11:38:36 -070069
70 // Save a copy of the last non-null DNS config
71 if (!config->properties().dns_servers.empty()) {
72 dns_servers_ = config->properties().dns_servers;
73 dns_domain_search_ = config->properties().domain_search;
74 }
75
76 if (is_default_) {
77 resolver_->SetDNSFromIPConfig(config);
78 }
79}
80
Paul Stewartc1dec4d2011-12-08 15:25:28 -080081void Connection::SetIsDefault(bool is_default) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080082 VLOG(2) << __func__ << " "
83 << interface_name_ << " (index " << interface_index_ << ") "
84 << is_default_ << " -> " << is_default;
Paul Stewartdd60e452011-08-08 11:38:36 -070085 if (is_default == is_default_) {
86 return;
87 }
88
Paul Stewart7cfca042011-12-08 14:18:17 -080089 routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
Paul Stewartdd60e452011-08-08 11:38:36 -070090
Paul Stewartc681fa02012-03-02 19:40:04 -080091 is_default_ = is_default;
92
Paul Stewartdd60e452011-08-08 11:38:36 -070093 if (is_default) {
94 resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
Paul Stewartc681fa02012-03-02 19:40:04 -080095 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
96 if (device) {
97 device->RequestPortalDetection();
98 }
Paul Stewartdd60e452011-08-08 11:38:36 -070099 }
Paul Stewartdd60e452011-08-08 11:38:36 -0700100}
101
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800102void Connection::RequestRouting() {
103 if (routing_request_count_++ == 0) {
104 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
105 DCHECK(device.get());
106 if (!device.get()) {
107 LOG(ERROR) << "Device is NULL!";
108 return;
109 }
110 device->DisableReversePathFilter();
111 }
112}
113
114void Connection::ReleaseRouting() {
115 DCHECK(routing_request_count_ > 0);
116 if (--routing_request_count_ == 0) {
117 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
118 DCHECK(device.get());
119 if (!device.get()) {
120 LOG(ERROR) << "Device is NULL!";
121 return;
122 }
123 device->EnableReversePathFilter();
124
125 // Clear any cached routes that might have accumulated while reverse-path
126 // filtering was disabled.
127 routing_table_->FlushCache();
128 }
129}
130
Paul Stewartf748a362012-03-07 12:01:20 -0800131bool Connection::RequestHostRoute(const IPAddress &address) {
132 // Set the prefix to be the entire address size.
133 IPAddress address_prefix(address);
134 address_prefix.set_prefix(address_prefix.GetLength() * 8);
135
136 if (!routing_table_->RequestRouteToHost(address_prefix, interface_index_)) {
137 LOG(ERROR) << "Could not request route to " << address.ToString();
138 return false;
139 }
140
141 return true;
142}
143
Paul Stewart7cfca042011-12-08 14:18:17 -0800144uint32 Connection::GetMetric(bool is_default) {
145 // If this is not the default route, assign a metric based on the interface
146 // index. This way all non-default routes (even to the same gateway IP) end
147 // up with unique metrics so they do not collide.
148 return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
149}
150
Paul Stewartdd60e452011-08-08 11:38:36 -0700151} // namespace shill