1//
2// Copyright (C) 2015 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 "dhcp_client/service.h"
18
19#include <string>
20
21#include "dhcp_client/device_info.h"
22#include "dhcp_client/manager.h"
23
24using std::string;
25
26namespace {
27const char kConstantInterfaceName[] = "interface_name";
28const char kConstantDHCPType[] = "type";
29const char kConstantNetworkIdentifier[] = "identifier";
30const char kConstantRequestHostname[] = "request_hostname";
31const char kConstantArpGateway[] = "arp_gateway";
32const char kConstantUnicastArp[] = "unicast_arp";
33const char kConstantRequestNontemporaryAddress[] = "request_na";
34const char kConstantRequestPrefixDelegation[] = "request_pf";
35}
36
37namespace dhcp_client {
38
39Service::Service(Manager* manager,
40                 int service_identifier,
41                 EventDispatcherInterface* event_dispatcher,
42                 const brillo::VariantDictionary& configs)
43    : manager_(manager),
44      identifier_(service_identifier),
45      event_dispatcher_(event_dispatcher),
46      type_(DHCP::SERVICE_TYPE_IPV4),
47      request_hostname_(false),
48      arp_gateway_(false),
49      unicast_arp_(false),
50      request_na_(false),
51      request_pd_(false) {
52  ParseConfigs(configs);
53}
54
55Service::~Service() {
56  Stop();
57}
58
59bool Service::Start() {
60  if (!DeviceInfo::GetInstance()->GetDeviceInfo(interface_name_,
61                                                &hardware_address_,
62                                                &interface_index_)) {
63    LOG(ERROR) << "Unable to get interface information for: "
64               << interface_name_;
65    return false;
66  }
67
68  if (type_ == DHCP::SERVICE_TYPE_IPV4 ||
69      type_ == DHCP::SERVICE_TYPE_BOTH) {
70    state_machine_ipv4_.reset(new DHCPV4(interface_name_,
71                                         hardware_address_,
72                                         interface_index_,
73                                         network_id_,
74                                         request_hostname_,
75                                         arp_gateway_,
76                                         unicast_arp_,
77                                         event_dispatcher_));
78  }
79  if (type_ == DHCP::SERVICE_TYPE_IPV6 ||
80      type_ == DHCP::SERVICE_TYPE_BOTH) {
81    // TODO(nywang): Create DHCP state machine for IPV6.
82  }
83  if (state_machine_ipv4_) {
84    state_machine_ipv4_->Start();
85  }
86  // TODO(nywang): Start DHCP state machine for IPV6.
87  return true;
88}
89
90void Service::Stop() {
91  if (state_machine_ipv4_) {
92    state_machine_ipv4_->Stop();
93    state_machine_ipv4_.reset();
94  }
95  // TODO(nywang): Stop DHCP state machine for IPV6.
96}
97
98void Service::ParseConfigs(const brillo::VariantDictionary& configs) {
99  for (const auto& key_and_value : configs) {
100    const std::string& key = key_and_value.first;
101    const auto& value = key_and_value.second;
102    if (key ==  kConstantInterfaceName && value.IsTypeCompatible<string>()) {
103      interface_name_ = value.Get<string>();
104    } else if (key == kConstantDHCPType && value.IsTypeCompatible<int32_t>()) {
105      type_  = static_cast<DHCP::ServiceType>(value.Get<int32_t>());
106    } else if (key == kConstantNetworkIdentifier &&
107               value.IsTypeCompatible<string>()) {
108      network_id_ = value.Get<string>();
109    } else if (key == kConstantRequestHostname &&
110               value.IsTypeCompatible<bool>()) {
111      request_hostname_ = value.Get<bool>();
112    } else if (key == kConstantArpGateway && value.IsTypeCompatible<bool>()) {
113      arp_gateway_ = value.Get<bool>();
114    } else if (key == kConstantUnicastArp && value.IsTypeCompatible<bool>()) {
115      unicast_arp_ = value.Get<bool>();
116    } else if (key == kConstantRequestNontemporaryAddress &&
117      value.IsTypeCompatible<bool>()) {
118      request_na_ = value.Get<bool>();
119    } else if (key == kConstantRequestPrefixDelegation &&
120               value.IsTypeCompatible<bool>()) {
121      request_pd_ = value.Get<bool>();
122    } else {
123      LOG(ERROR) << "Invalid configuration with key: " << key;
124    }
125  }
126}
127
128}  // namespace dhcp_client
129
130