blob: 5d549a43c4dc6d6f0b4e5d2fed291a0f4dbd66eb [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_);
Paul Stewart9a908082011-08-31 12:18:48 -070042 routing_table_->FlushRoutes(interface_index_);
43 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
69 // Save a copy of the last non-null DNS config
70 if (!config->properties().dns_servers.empty()) {
71 dns_servers_ = config->properties().dns_servers;
72 dns_domain_search_ = config->properties().domain_search;
73 }
74
75 if (is_default_) {
76 resolver_->SetDNSFromIPConfig(config);
77 }
78}
79
Paul Stewartc1dec4d2011-12-08 15:25:28 -080080void Connection::SetIsDefault(bool is_default) {
mukesh agrawal2c15d2c2012-02-21 16:09:21 -080081 VLOG(2) << __func__ << " "
82 << interface_name_ << " (index " << interface_index_ << ") "
83 << is_default_ << " -> " << is_default;
Paul Stewartdd60e452011-08-08 11:38:36 -070084 if (is_default == is_default_) {
85 return;
86 }
87
Paul Stewart7cfca042011-12-08 14:18:17 -080088 routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
Paul Stewartdd60e452011-08-08 11:38:36 -070089
90 if (is_default) {
91 resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
92 }
93
94 is_default_ = is_default;
95}
96
Paul Stewartc8f4bef2011-12-13 09:45:51 -080097void Connection::RequestRouting() {
98 if (routing_request_count_++ == 0) {
99 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
100 DCHECK(device.get());
101 if (!device.get()) {
102 LOG(ERROR) << "Device is NULL!";
103 return;
104 }
105 device->DisableReversePathFilter();
106 }
107}
108
109void Connection::ReleaseRouting() {
110 DCHECK(routing_request_count_ > 0);
111 if (--routing_request_count_ == 0) {
112 DeviceRefPtr device = device_info_->GetDevice(interface_index_);
113 DCHECK(device.get());
114 if (!device.get()) {
115 LOG(ERROR) << "Device is NULL!";
116 return;
117 }
118 device->EnableReversePathFilter();
119
120 // Clear any cached routes that might have accumulated while reverse-path
121 // filtering was disabled.
122 routing_table_->FlushCache();
123 }
124}
125
Paul Stewart7cfca042011-12-08 14:18:17 -0800126uint32 Connection::GetMetric(bool is_default) {
127 // If this is not the default route, assign a metric based on the interface
128 // index. This way all non-default routes (even to the same gateway IP) end
129 // up with unique metrics so they do not collide.
130 return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
131}
132
Paul Stewartdd60e452011-08-08 11:38:36 -0700133} // namespace shill