blob: bc5a5751cdbb3faf645f77fd040e1eb22be4e4d4 [file] [log] [blame]
Peter Qiu24b34a02015-06-30 10:22:26 -07001// Copyright 2015 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/chromeos_daemon.h"
6
7#include <string>
8
9#include <base/bind.h>
10
11#include "shill/control_interface.h"
12#include "shill/dhcp/dhcp_provider.h"
13#include "shill/diagnostics_reporter.h"
14#include "shill/error.h"
15#include "shill/logging.h"
16#include "shill/manager.h"
17#include "shill/net/ndisc.h"
18#include "shill/net/rtnl_handler.h"
Peter Qiu24b34a02015-06-30 10:22:26 -070019#include "shill/routing_table.h"
20#include "shill/shill_config.h"
21
22#if !defined(DISABLE_WIFI)
23#include "shill/net/netlink_manager.h"
24#include "shill/net/nl80211_message.h"
25#endif // DISABLE_WIFI
26
27using base::Bind;
28using base::Unretained;
29using std::string;
30using std::vector;
31
32namespace shill {
33
34namespace Logging {
35static auto kModuleLogScope = ScopeLogger::kDaemon;
36static string ObjectID(ChromeosDaemon* d) { return "(shill_daemon)"; }
37}
38
39
40ChromeosDaemon::ChromeosDaemon(const Settings& settings,
41 Config* config,
42 ControlInterface* control)
43 : config_(config),
44 control_(control),
45 metrics_(new Metrics(&dispatcher_)),
Peter Qiu24b34a02015-06-30 10:22:26 -070046 rtnl_handler_(RTNLHandler::GetInstance()),
47 routing_table_(RoutingTable::GetInstance()),
48 dhcp_provider_(DHCPProvider::GetInstance()),
49#if !defined(DISABLE_WIFI)
50 netlink_manager_(NetlinkManager::GetInstance()),
51 callback80211_metrics_(metrics_.get()),
52#endif // DISABLE_WIFI
53 manager_(new Manager(control_.get(),
54 &dispatcher_,
55 metrics_.get(),
56 &glib_,
57 config->GetRunDirectory(),
58 config->GetStorageDirectory(),
59 config->GetUserStorageDirectory())) {
60 ApplySettings(settings);
61}
62
63ChromeosDaemon::~ChromeosDaemon() {}
64
65void ChromeosDaemon::ApplySettings(const Settings& settings) {
66 for (const auto& device_name : settings.device_blacklist) {
67 manager_->AddDeviceToBlackList(device_name);
68 }
69 Error error;
70 manager_->SetTechnologyOrder(settings.default_technology_order, &error);
71 CHECK(error.IsSuccess()); // Command line should have been validated.
72 manager_->SetIgnoreUnknownEthernet(settings.ignore_unknown_ethernet);
73 if (settings.use_portal_list) {
74 manager_->SetStartupPortalList(settings.portal_list);
75 }
76 if (settings.passive_mode) {
77 manager_->SetPassiveMode();
78 }
79 manager_->SetPrependDNSServers(settings.prepend_dns_servers);
80 if (settings.minimum_mtu) {
81 manager_->SetMinimumMTU(settings.minimum_mtu);
82 }
83 manager_->SetAcceptHostnameFrom(settings.accept_hostname_from);
84 manager_->SetDHCPv6EnabledDevices(settings.dhcpv6_enabled_devices);
85}
86
87void ChromeosDaemon::Quit() {
88 SLOG(this, 1) << "Starting termination actions.";
89 if (!manager_->RunTerminationActionsAndNotifyMetrics(
90 Bind(&ChromeosDaemon::TerminationActionsCompleted,
91 Unretained(this)))) {
92 SLOG(this, 1) << "No termination actions were run";
93 StopAndReturnToMain();
94 }
95}
96
97void ChromeosDaemon::TerminationActionsCompleted(const Error& error) {
98 SLOG(this, 1) << "Finished termination actions. Result: " << error;
99 metrics_->NotifyTerminationActionsCompleted(error.IsSuccess());
100
101 // Daemon::TerminationActionsCompleted() should not directly call
102 // Daemon::Stop(). Otherwise, it could lead to the call sequence below. That
103 // is not safe as the HookTable's start callback only holds a weak pointer to
104 // the Cellular object, which is destroyed in midst of the
105 // Cellular::OnTerminationCompleted() call. We schedule the
106 // Daemon::StopAndReturnToMain() call through the message loop instead.
107 //
108 // Daemon::Quit
109 // -> Manager::RunTerminationActionsAndNotifyMetrics
110 // -> Manager::RunTerminationActions
111 // -> HookTable::Run
112 // ...
113 // -> Cellular::OnTerminationCompleted
114 // -> Manager::TerminationActionComplete
115 // -> HookTable::ActionComplete
116 // -> Daemon::TerminationActionsCompleted
117 // -> Daemon::Stop
118 // -> Manager::Stop
119 // -> DeviceInfo::Stop
120 // -> Cellular::~Cellular
121 // -> Manager::RemoveTerminationAction
122 dispatcher_.PostTask(
123 Bind(&ChromeosDaemon::StopAndReturnToMain, Unretained(this)));
124}
125
126void ChromeosDaemon::StopAndReturnToMain() {
127 Stop();
128 dispatcher_.PostTask(base::MessageLoop::QuitClosure());
129}
130
131void ChromeosDaemon::Start() {
132 glib_.TypeInit();
133 metrics_->Start();
134 rtnl_handler_->Start(
135 RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
136 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE | RTMGRP_ND_USEROPT);
137 routing_table_->Start();
138 dhcp_provider_->Init(control_.get(), &dispatcher_, &glib_, metrics_.get());
139
140#if !defined(DISABLE_WIFI)
141 if (netlink_manager_) {
142 netlink_manager_->Init();
143 uint16_t nl80211_family_id = netlink_manager_->GetFamily(
144 Nl80211Message::kMessageTypeString,
145 Bind(&Nl80211Message::CreateMessage));
146 if (nl80211_family_id == NetlinkMessage::kIllegalMessageType) {
147 LOG(FATAL) << "Didn't get a legal message type for 'nl80211' messages.";
148 }
149 Nl80211Message::SetMessageType(nl80211_family_id);
150 netlink_manager_->Start();
151
152 // Install handlers for NetlinkMessages that don't have specific handlers
153 // (which are registered by message sequence number).
154 netlink_manager_->AddBroadcastHandler(Bind(
155 &Callback80211Metrics::CollectDisconnectStatistics,
156 callback80211_metrics_.AsWeakPtr()));
157 }
158#endif // DISABLE_WIFI
159
160 manager_->Start();
161}
162
163void ChromeosDaemon::Stop() {
164 manager_->Stop();
165 manager_ = nullptr; // Release manager resources, including DBus adaptor.
166 metrics_->Stop();
167 dhcp_provider_->Stop();
168}
169
170} // namespace shill