connection.cc revision 7cfca0467e47aa91b485c485b92befb33a1fd61f
1// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// 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
7#include <arpa/inet.h>
8#include <linux/rtnetlink.h>
9
10#include "shill/device_info.h"
11#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
22const uint32 Connection::kNonDefaultMetricBase = 10;
23
24Connection::Connection(int interface_index,
25                       const std::string& interface_name,
26                       const DeviceInfo *device_info)
27    : is_default_(false),
28      interface_index_(interface_index),
29      interface_name_(interface_name),
30      device_info_(device_info),
31      resolver_(Resolver::GetInstance()),
32      routing_table_(RoutingTable::GetInstance()),
33      rtnl_handler_(RTNLHandler::GetInstance()) {
34  VLOG(2) << __func__;
35}
36
37Connection::~Connection() {
38  VLOG(2) << __func__;
39
40  routing_table_->FlushRoutes(interface_index_);
41  device_info_->FlushAddresses(interface_index_);
42}
43
44void Connection::UpdateFromIPConfig(const IPConfigRefPtr &config) {
45  VLOG(2) << __func__;
46
47  const IPConfig::Properties &properties = config->properties();
48  IPAddress local(properties.address_family);
49  if (!local.SetAddressFromString(properties.address)) {
50    LOG(ERROR) << "Local address " << properties.address << " is invalid";
51    return;
52  }
53  local.set_prefix(properties.subnet_cidr);
54
55  IPAddress broadcast(properties.address_family);
56  if (!broadcast.SetAddressFromString(properties.broadcast_address)) {
57    LOG(ERROR) << "Broadcast address " << properties.broadcast_address
58               << " is invalid";
59    return;
60  }
61
62  rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
63
64  routing_table_->SetDefaultRoute(interface_index_, config,
65                                  GetMetric(is_default_));
66
67  // Save a copy of the last non-null DNS config
68  if (!config->properties().dns_servers.empty()) {
69    dns_servers_ = config->properties().dns_servers;
70    dns_domain_search_ = config->properties().domain_search;
71  }
72
73  if (is_default_) {
74    resolver_->SetDNSFromIPConfig(config);
75  }
76}
77
78void Connection::SetDefault(bool is_default) {
79  VLOG(2) << __func__;
80  if (is_default == is_default_) {
81    return;
82  }
83
84  routing_table_->SetDefaultMetric(interface_index_, GetMetric(is_default));
85
86  if (is_default) {
87    resolver_->SetDNSFromLists(dns_servers_, dns_domain_search_);
88  }
89
90  is_default_ = is_default;
91}
92
93uint32 Connection::GetMetric(bool is_default) {
94  // If this is not the default route, assign a metric based on the interface
95  // index.  This way all non-default routes (even to the same gateway IP) end
96  // up with unique metrics so they do not collide.
97  return is_default ? kDefaultMetric : kNonDefaultMetricBase + interface_index_;
98}
99
100}  // namespace shill
101