Index: l2tp_manager.cc |
diff --git a/l2tp_manager.cc b/l2tp_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..18e62df5bbb5d7636153692fb3342edc2015b6b8 |
--- /dev/null |
+++ b/l2tp_manager.cc |
@@ -0,0 +1,205 @@ |
+// 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(ppp_setup_timeout, 10, "timeout to setup ppp (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"; |
Will Drewry
2011/03/05 04:06:39
nice!
kmixter1
2011/03/11 01:34:27
Done.
|
+ |
+using ::chromeos::ProcessImpl; |
+ |
+L2tpManager::L2tpManager() |
+ : ServiceManager("l2tp"), |
+ was_initiated_(false), |
+ output_fd_(-1), |
+ ppp_interface_path_(kPppInterfacePath), |
+ 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())); |
Will Drewry
2011/03/05 04:06:39
Is the password being passed in on the commandline
kmixter1
2011/03/11 01:34:27
Exactly - it's for testing only. Warning added.
|
+ } 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; |
+ } |
+ was_initiated_ = true; |
+ 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); |
+ start_ticks_ = base::TimeTicks::Now(); |
+ return true; |
+} |
+ |
+int L2tpManager::Poll() { |
+ if (is_running()) return -1; |
+ if (start_ticks_.is_null()) return -1; |
+ if (!was_initiated_ && file_util::PathExists(l2tpd_control_path_)) { |
+ if (!Initiate()) { |
+ LOG(ERROR) << "Unable to initiate connection"; |
+ Terminate(); |
+ OnStopped(false); |
+ return -1; |
+ } |
+ // With the connection initated, check if it's up in 1s. |
+ return 1000; |
+ } |
+ if (was_initiated_ && file_util::PathExists(FilePath(ppp_interface_path_))) { |
+ LOG(INFO) << "L2TP connection now up"; |
+ OnStarted(); |
+ return -1; |
+ } |
+ // Check for the ppp setup timeout. This includes the time |
+ // to start pppd, it to set up its control file, l2tp connection |
+ // setup, ppp connection setup. Authentication happens after |
+ // the ppp device is created. |
+ if (base::TimeTicks::Now() - start_ticks_ > |
+ base::TimeDelta::FromSeconds(FLAGS_ppp_setup_timeout)) { |
+ LOG(ERROR) << "PPP setup timed out"; |
+ // Cleanly terminate if the control file exists. |
+ if (was_initiated_) Terminate(); |
+ OnStopped(false); |
+ // Poll in 1 second in order to check if clean shutdown worked. |
+ } |
+ return 1000; |
+} |
+ |
+void L2tpManager::ProcessOutput() { |
+ ServiceManager::WriteFdToSyslog(output_fd_, ""); |
+} |
+ |
+bool L2tpManager::IsChild(pid_t pid) { |
+ return pid == l2tpd_->pid(); |
+} |
+ |
+void L2tpManager::Stop() { |
+ if (l2tpd_->pid()) { |
+ LOG(INFO) << "Shutting down L2TP"; |
+ Terminate(); |
+ } |
+ OnStopped(false); |
+} |