1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/ethernet/ethernet_service.h"
18
19#include <netinet/ether.h>
20#if defined(__ANDROID__)
21#include <net/if.h>
22#else
23#include <linux/if.h>  // NOLINT - Needs definitions from netinet/ether.h
24#endif  // __ANDROID__
25#include <stdio.h>
26#include <time.h>
27
28#include <string>
29
30#include <base/strings/stringprintf.h>
31#if defined(__ANDROID__)
32#include <dbus/service_constants.h>
33#else
34#include <chromeos/dbus/service_constants.h>
35#endif  // __ANDROID__
36
37#include "shill/control_interface.h"
38#include "shill/device.h"
39#include "shill/device_info.h"
40#include "shill/eap_credentials.h"
41#include "shill/ethernet/ethernet.h"
42#include "shill/event_dispatcher.h"
43#include "shill/manager.h"
44#include "shill/profile.h"
45
46using std::string;
47
48namespace shill {
49
50// static
51const char EthernetService::kAutoConnNoCarrier[] = "no carrier";
52const char EthernetService::kServiceType[] = "ethernet";
53
54EthernetService::EthernetService(ControlInterface* control_interface,
55                                 EventDispatcher* dispatcher,
56                                 Metrics* metrics,
57                                 Manager* manager,
58                                 base::WeakPtr<Ethernet> ethernet)
59    : EthernetService(control_interface, dispatcher, metrics, manager,
60                      Technology::kEthernet, ethernet) {
61  SetConnectable(true);
62  SetAutoConnect(true);
63  set_friendly_name("Ethernet");
64  SetStrength(kStrengthMax);
65
66  // Now that |this| is a fully constructed EthernetService, synchronize
67  // observers with our current state, and emit the appropriate change
68  // notifications. (Initial observer state may have been set in our base
69  // class.)
70  NotifyPropertyChanges();
71}
72
73EthernetService::EthernetService(ControlInterface* control_interface,
74                                 EventDispatcher* dispatcher,
75                                 Metrics* metrics,
76                                 Manager* manager,
77                                 Technology::Identifier technology,
78                                 base::WeakPtr<Ethernet> ethernet)
79  : Service(control_interface, dispatcher, metrics, manager, technology),
80    ethernet_(ethernet) {}
81
82EthernetService::~EthernetService() { }
83
84void EthernetService::Connect(Error* error, const char* reason) {
85  Service::Connect(error, reason);
86  CHECK(ethernet_);
87  ethernet_->ConnectTo(this);
88}
89
90void EthernetService::Disconnect(Error* error, const char* reason) {
91  Service::Disconnect(error, reason);
92  CHECK(ethernet_);
93  ethernet_->DisconnectFrom(this);
94}
95
96std::string EthernetService::GetDeviceRpcId(Error* /*error*/) const {
97  CHECK(ethernet_);
98  return ethernet_->GetRpcIdentifier();
99}
100
101string EthernetService::GetStorageIdentifier() const {
102  CHECK(ethernet_);
103  return base::StringPrintf(
104      "%s_%s", Technology::NameFromIdentifier(technology()).c_str(),
105      ethernet_->address().c_str());
106}
107
108bool EthernetService::IsAutoConnectByDefault() const {
109  return true;
110}
111
112bool EthernetService::SetAutoConnectFull(const bool& connect,
113                                         Error* error) {
114  if (!connect) {
115    Error::PopulateAndLog(
116        FROM_HERE, error, Error::kInvalidArguments,
117        "Auto-connect on Ethernet services must not be disabled.");
118    return false;
119  }
120  return Service::SetAutoConnectFull(connect, error);
121}
122
123void EthernetService::Remove(Error* error) {
124  error->Populate(Error::kNotSupported);
125}
126
127bool EthernetService::IsVisible() const {
128  CHECK(ethernet_);
129  return ethernet_->link_up();
130}
131
132bool EthernetService::IsAutoConnectable(const char** reason) const {
133  if (!Service::IsAutoConnectable(reason)) {
134    return false;
135  }
136  CHECK(ethernet_);
137  if (!ethernet_->link_up()) {
138    *reason = kAutoConnNoCarrier;
139    return false;
140  }
141  return true;
142}
143
144void EthernetService::OnVisibilityChanged() {
145  NotifyPropertyChanges();
146}
147
148string EthernetService::GetTethering(Error* /*error*/) const {
149  CHECK(ethernet_);
150  return ethernet_->IsConnectedViaTether() ? kTetheringConfirmedState :
151      kTetheringNotDetectedState;
152}
153
154}  // namespace shill
155