182 lines
6.1 KiB
C++
182 lines
6.1 KiB
C++
//
|
|
// Copyright (C) 2015 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/dhcp/dhcpv6_config.h"
|
|
|
|
#include <base/files/file_util.h>
|
|
#include <base/strings/stringprintf.h>
|
|
#if defined(__ANDROID__)
|
|
#include <dbus/service_constants.h>
|
|
#else
|
|
#include <chromeos/dbus/service_constants.h>
|
|
#endif // __ANDROID__
|
|
|
|
#include "shill/dhcp/dhcp_provider.h"
|
|
#include "shill/logging.h"
|
|
#include "shill/net/ip_address.h"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
namespace shill {
|
|
|
|
namespace Logging {
|
|
static auto kModuleLogScope = ScopeLogger::kDHCP;
|
|
static string ObjectID(DHCPv6Config* d) {
|
|
if (d == nullptr)
|
|
return "(DHCPv6_config)";
|
|
else
|
|
return d->device_name();
|
|
}
|
|
}
|
|
|
|
// static
|
|
const char DHCPv6Config::kDHCPCDPathFormatPID[] =
|
|
"var/run/dhcpcd/dhcpcd-%s-6.pid";
|
|
|
|
const char DHCPv6Config::kConfigurationKeyDelegatedPrefix[] =
|
|
"DHCPv6DelegatedPrefix";
|
|
const char DHCPv6Config::kConfigurationKeyDelegatedPrefixLength[] =
|
|
"DHCPv6DelegatedPrefixLength";
|
|
const char DHCPv6Config::kConfigurationKeyDelegatedPrefixLeaseTime[] =
|
|
"DHCPv6DelegatedPrefixLeaseTime";
|
|
const char DHCPv6Config::kConfigurationKeyDNS[] = "DHCPv6NameServers";
|
|
const char DHCPv6Config::kConfigurationKeyDomainSearch[] = "DHCPv6DomainSearch";
|
|
const char DHCPv6Config::kConfigurationKeyIPAddress[] = "DHCPv6Address";
|
|
const char DHCPv6Config::kConfigurationKeyIPAddressLeaseTime[] =
|
|
"DHCPv6AddressLeaseTime";
|
|
const char DHCPv6Config::kConfigurationKeyServerIdentifier[] =
|
|
"DHCPv6ServerIdentifier";
|
|
|
|
const char DHCPv6Config::kReasonBound[] = "BOUND6";
|
|
const char DHCPv6Config::kReasonFail[] = "FAIL6";
|
|
const char DHCPv6Config::kReasonRebind[] = "REBIND6";
|
|
const char DHCPv6Config::kReasonReboot[] = "REBOOT6";
|
|
const char DHCPv6Config::kReasonRenew[] = "RENEW6";
|
|
|
|
const char DHCPv6Config::kType[] = "dhcp6";
|
|
|
|
DHCPv6Config::DHCPv6Config(ControlInterface* control_interface,
|
|
EventDispatcher* dispatcher,
|
|
DHCPProvider* provider,
|
|
const string& device_name,
|
|
const string& lease_file_suffix)
|
|
: DHCPConfig(control_interface,
|
|
dispatcher,
|
|
provider,
|
|
device_name,
|
|
kType,
|
|
lease_file_suffix) {
|
|
SLOG(this, 2) << __func__ << ": " << device_name;
|
|
}
|
|
|
|
DHCPv6Config::~DHCPv6Config() {
|
|
SLOG(this, 2) << __func__ << ": " << device_name();
|
|
}
|
|
|
|
void DHCPv6Config::ProcessEventSignal(const string& reason,
|
|
const KeyValueStore& configuration) {
|
|
LOG(INFO) << "Event reason: " << reason;
|
|
if (reason == kReasonFail) {
|
|
LOG(ERROR) << "Received failure event from DHCPv6 client.";
|
|
NotifyFailure();
|
|
return;
|
|
} else if (reason != kReasonBound &&
|
|
reason != kReasonRebind &&
|
|
reason != kReasonReboot &&
|
|
reason != kReasonRenew) {
|
|
LOG(WARNING) << "Event ignored.";
|
|
return;
|
|
}
|
|
|
|
CHECK(ParseConfiguration(configuration));
|
|
|
|
// This needs to be set before calling UpdateProperties() below since
|
|
// those functions may indirectly call other methods like ReleaseIP that
|
|
// depend on or change this value.
|
|
set_is_lease_active(true);
|
|
|
|
DHCPConfig::UpdateProperties(properties_, true);
|
|
}
|
|
|
|
void DHCPv6Config::ProcessStatusChangeSignal(const string& status) {
|
|
SLOG(this, 2) << __func__ << ": " << status;
|
|
// TODO(zqiu): metric reporting for status.
|
|
}
|
|
|
|
void DHCPv6Config::CleanupClientState() {
|
|
DHCPConfig::CleanupClientState();
|
|
|
|
// Delete lease file if it is ephemeral.
|
|
if (IsEphemeralLease()) {
|
|
base::DeleteFile(root().Append(
|
|
base::StringPrintf(DHCPProvider::kDHCPCDPathFormatLease6,
|
|
device_name().c_str())), false);
|
|
}
|
|
base::DeleteFile(root().Append(
|
|
base::StringPrintf(kDHCPCDPathFormatPID, device_name().c_str())), false);
|
|
|
|
// Reset configuration data.
|
|
properties_ = IPConfig::Properties();
|
|
}
|
|
|
|
vector<string> DHCPv6Config::GetFlags() {
|
|
// Get default flags first.
|
|
vector<string> flags = DHCPConfig::GetFlags();
|
|
|
|
flags.push_back("-6"); // IPv6 only.
|
|
flags.push_back("-a"); // Request ia_na and ia_pd.
|
|
return flags;
|
|
}
|
|
|
|
bool DHCPv6Config::ParseConfiguration(const KeyValueStore& configuration) {
|
|
SLOG(nullptr, 2) << __func__;
|
|
properties_.method = kTypeDHCP6;
|
|
properties_.address_family = IPAddress::kFamilyIPv6;
|
|
for (const auto it : configuration.properties()) {
|
|
const string& key = it.first;
|
|
const brillo::Any& value = it.second;
|
|
SLOG(nullptr, 2) << "Processing key: " << key;
|
|
if (key == kConfigurationKeyIPAddress) {
|
|
properties_.address = value.Get<string>();
|
|
} else if (key == kConfigurationKeyDNS) {
|
|
properties_.dns_servers = value.Get<vector<string>>();
|
|
} else if (key == kConfigurationKeyDomainSearch) {
|
|
properties_.domain_search = value.Get<vector<string>>();
|
|
} else if (key == kConfigurationKeyIPAddressLeaseTime ||
|
|
key == kConfigurationKeyDelegatedPrefixLeaseTime) {
|
|
UpdateLeaseTime(value.Get<uint32_t>());
|
|
} else if (key == kConfigurationKeyDelegatedPrefix) {
|
|
properties_.delegated_prefix = value.Get<string>();
|
|
} else if (key == kConfigurationKeyDelegatedPrefixLength) {
|
|
properties_.delegated_prefix_length = value.Get<uint32_t>();
|
|
} else {
|
|
SLOG(nullptr, 2) << "Key ignored.";
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void DHCPv6Config::UpdateLeaseTime(uint32_t lease_time) {
|
|
// IP address and delegated prefix are provided as separate lease. Use
|
|
// the shorter time of the two lease as the lease time.
|
|
if (properties_.lease_duration_seconds == 0 ||
|
|
lease_time < properties_.lease_duration_seconds) {
|
|
properties_.lease_duration_seconds = lease_time;
|
|
}
|
|
}
|
|
|
|
} // namespace shill
|