Chromium Code Reviews| Index: l2tp_manager.cc |
| diff --git a/l2tp_manager.cc b/l2tp_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..bfd77e82dd3eeaa1194ec53d9c08eb30d1994e6f |
| --- /dev/null |
| +++ b/l2tp_manager.cc |
| @@ -0,0 +1,189 @@ |
| +// Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "vpn-manager/l2tp_manager.h" |
| + |
| +#include "base/file_util.h" |
| +#include "base/logging.h" |
| +#include "base/string_util.h" |
| +#include "chromeos/process.h" |
| +#include "gflags/gflags.h" |
| + |
| +#pragma GCC diagnostic ignored "-Wstrict-aliasing" |
| +DEFINE_bool(require_chap, true, "require chap"); |
| +DEFINE_bool(refuse_pap, true, "refuse chap"); |
| +DEFINE_bool(require_authentication, true, "require authentication"); |
| +DEFINE_bool(ppp_debug, true, "ppp debug"); |
| +DEFINE_bool(length_bit, true, "length bit"); |
| +DEFINE_int32(authentication_timeout, 10, "timeout to authenticate (seconds)"); |
| +DEFINE_string(pppd_plugin, "", "pppd plugin"); |
| +DEFINE_string(user, "", "user name"); |
| +DEFINE_string(password, "", "password"); |
| +#pragma GCC diagnostic error "-Wstrict-aliasing" |
| + |
| +const char kL2tpConnectionName[] = "managed"; |
| +const char kPppInterfacePath[] = "/sys/class/net/ppp0"; |
| + |
| +using ::chromeos::ProcessImpl; |
| + |
| +// TODO: enable PPPoL2TP or at least measure efficiency gap. |
|
petkov
2011/03/04 18:42:56
TODO(kmixter)
kmixter1
2011/03/05 02:48:59
Removed here and added crosbug.com/12769
|
| + |
| +L2tpManager::L2tpManager() : ServiceManager("l2tp"), output_fd_(-1), |
|
petkov
2011/03/04 18:42:56
initializers on separate lines?
kmixter1
2011/03/05 02:48:59
Done.
|
| + l2tpd_(new ProcessImpl) { |
| +} |
| + |
| +bool L2tpManager::Initialize(const std::string& remote) { |
| + remote_ = remote; |
| + if (FLAGS_user.empty()) { |
| + LOG(ERROR) << "l2tp layer requires user name"; |
| + return false; |
| + } |
| + if (!FLAGS_pppd_plugin.empty() && |
| + !file_util::PathExists(FilePath(FLAGS_pppd_plugin))) { |
| + LOG(WARNING) << "pppd_plugin (" << FLAGS_pppd_plugin << ") does not exist."; |
| + } |
| + return true; |
| +} |
| + |
| +static void AddString(std::string* config, const char* key, |
| + const std::string& value) { |
| + config->append(StringPrintf("%s = %s\n", key, value.c_str())); |
| +} |
| + |
| +static void AddBool(std::string* config, const char* key, bool value) { |
| + config->append(StringPrintf("%s = %s\n", key, value ? "yes" : "no")); |
| +} |
| + |
| +std::string L2tpManager::FormatL2tpdConfiguration( |
| + const std::string& ppp_config_path) { |
| + std::string l2tpd_config; |
| + l2tpd_config.append(StringPrintf("[lac %s]\n", kL2tpConnectionName)); |
| + AddString(&l2tpd_config, "lns", remote_); |
| + AddBool(&l2tpd_config, "require chap", FLAGS_require_chap); |
| + AddBool(&l2tpd_config, "refuse pap", FLAGS_refuse_pap); |
| + AddBool(&l2tpd_config, "require authentication", |
| + FLAGS_require_authentication); |
| + AddString(&l2tpd_config, "name", FLAGS_user); |
| + AddBool(&l2tpd_config, "ppp debug", FLAGS_ppp_debug); |
| + AddString(&l2tpd_config, "pppoptfile", ppp_config_path); |
| + AddBool(&l2tpd_config, "length bit", FLAGS_length_bit); |
| + return l2tpd_config; |
| +} |
| + |
| +std::string L2tpManager::FormatPppdConfiguration() { |
| + std::string pppd_config = StringPrintf( |
| + "ipcp-accept-local\n" |
| + "ipcp-accept-remote\n" |
| + "refuse-eap\n" |
| + "noccp\n" |
| + "noauth\n" |
| + "crtscts\n" |
| + "idle 1800\n" |
| + "mtu 1410\n" |
| + "mru 1410\n" |
| + "nodefaultroute\n" |
| + "debug\n" |
| + "lock\n" |
| + "connect-delay 5000\n"); |
| + if (!FLAGS_pppd_plugin.empty()) { |
| + DLOG(INFO) << "Using pppd plugin " << FLAGS_pppd_plugin; |
| + pppd_config.append(StringPrintf("plugin %s\n", FLAGS_pppd_plugin.c_str())); |
| + } |
| + return pppd_config; |
| +} |
| + |
| +bool L2tpManager::Initiate() { |
| + std::string control_string; |
| + control_string = StringPrintf("c %s", kL2tpConnectionName); |
| + if (FLAGS_pppd_plugin.empty()) { |
| + control_string.append(StringPrintf(" %s %s\n", |
| + FLAGS_user.c_str(), |
| + FLAGS_password.c_str())); |
| + } else { |
| + // otherwise the plugin must specify username and password. |
| + control_string.append("\n"); |
| + } |
| + if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), |
| + control_string.size())) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool L2tpManager::Terminate() { |
| + std::string control_string = StringPrintf("d %s\n", |
| + kL2tpConnectionName); |
| + if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), |
| + control_string.size())) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool L2tpManager::Start() { |
| + FilePath pppd_config_path = temp_path_.Append("pppd.conf"); |
| + std::string l2tpd_config = FormatL2tpdConfiguration(pppd_config_path.value()); |
| + FilePath l2tpd_config_path = temp_path_.Append("l2tpd.conf"); |
| + if (!file_util::WriteFile(l2tpd_config_path, l2tpd_config.c_str(), |
| + l2tpd_config.size())) { |
| + LOG(ERROR) << "Unable to write l2tpd config to " |
| + << l2tpd_config_path.value(); |
| + return false; |
| + } |
| + std::string pppd_config = FormatPppdConfiguration(); |
| + if (!file_util::WriteFile(pppd_config_path, pppd_config.c_str(), |
| + pppd_config.size())) { |
| + LOG(ERROR) << "Unable to write pppd config to " << pppd_config_path.value(); |
| + return false; |
| + } |
| + l2tpd_control_path_ = temp_path_.Append("l2tpd.control"); |
| + file_util::Delete(l2tpd_control_path_, false); |
| + l2tpd_->Reset(0); |
| + l2tpd_->AddArg(L2TPD); |
| + l2tpd_->AddStringOption("-c", l2tpd_config_path.value()); |
| + l2tpd_->AddStringOption("-C", l2tpd_control_path_.value()); |
| + l2tpd_->AddArg("-D"); |
| + l2tpd_->RedirectUsingPipe(STDERR_FILENO, false); |
| + l2tpd_->Start(); |
| + output_fd_ = l2tpd_->GetPipe(STDERR_FILENO); |
| + // TODO: better synchronization - maybe wait for file to appear. |
|
petkov
2011/03/04 18:42:56
TODO(kmixter)
kmixter1
2011/03/05 02:48:59
Done.
|
| + sleep(1); |
| + bool result = Initiate(); |
| + start_ticks_ = base::TimeTicks::Now(); |
| + return result; |
| +} |
| + |
| +// TODO: unit test this |
| +int L2tpManager::Poll() { |
| + if (is_running()) return -1; |
| + if (start_ticks_.is_null()) return -1; |
| + if (!file_util::PathExists(FilePath(kPppInterfacePath))) { |
| + if ((base::TimeTicks::Now() - start_ticks_).InSecondsF() > |
|
petkov
2011/03/04 18:42:56
why InSecondsF rather than InSeconds? also, I've u
kmixter1
2011/03/05 02:48:59
Not entirely sure why that form is better, but cha
|
| + FLAGS_authentication_timeout) { |
| + LOG(ERROR) << "PPP authentication timed out."; |
| + Terminate(); |
| + OnStopped(false); |
| + // Return 1 in order to get check exit conditions. |
|
petkov
2011/03/04 18:42:56
return 1000?
kmixter1
2011/03/05 02:48:59
Done.
|
| + } |
| + return 1000; |
| + } |
| + LOG(INFO) << "L2TP connection now up"; |
| + OnStarted(); |
| + return -1; |
| +} |
| + |
| +void L2tpManager::HandleChild(pid_t pid, int signal) { |
| + if (pid != l2tpd_->pid()) return; |
| + |
| + LOG(INFO) << "L2TP layer stopped"; |
| + OnStopped(true); |
| +} |
| + |
| +void L2tpManager::Stop() { |
| + if (l2tpd_->pid()) { |
| + LOG(INFO) << "Shutting down L2TP"; |
| + Terminate(); |
| + } |
| + OnStopped(false); |
| +} |