Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "vpn-manager/l2tp_manager.h" | |
| 6 | |
| 7 #include "base/file_util.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/string_util.h" | |
| 10 #include "chromeos/process.h" | |
| 11 #include "gflags/gflags.h" | |
| 12 | |
| 13 #pragma GCC diagnostic ignored "-Wstrict-aliasing" | |
| 14 DEFINE_bool(require_chap, true, "require chap"); | |
| 15 DEFINE_bool(refuse_pap, true, "refuse chap"); | |
| 16 DEFINE_bool(require_authentication, true, "require authentication"); | |
| 17 DEFINE_bool(ppp_debug, true, "ppp debug"); | |
| 18 DEFINE_bool(length_bit, true, "length bit"); | |
| 19 DEFINE_int32(authentication_timeout, 10, "timeout to authenticate (seconds)"); | |
| 20 DEFINE_string(pppd_plugin, "", "pppd plugin"); | |
| 21 DEFINE_string(user, "", "user name"); | |
| 22 DEFINE_string(password, "", "password"); | |
| 23 #pragma GCC diagnostic error "-Wstrict-aliasing" | |
| 24 | |
| 25 const char kL2tpConnectionName[] = "managed"; | |
| 26 const char kPppInterfacePath[] = "/sys/class/net/ppp0"; | |
| 27 | |
| 28 using ::chromeos::ProcessImpl; | |
| 29 | |
| 30 // 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
| |
| 31 | |
| 32 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.
| |
| 33 l2tpd_(new ProcessImpl) { | |
| 34 } | |
| 35 | |
| 36 bool L2tpManager::Initialize(const std::string& remote) { | |
| 37 remote_ = remote; | |
| 38 if (FLAGS_user.empty()) { | |
| 39 LOG(ERROR) << "l2tp layer requires user name"; | |
| 40 return false; | |
| 41 } | |
| 42 if (!FLAGS_pppd_plugin.empty() && | |
| 43 !file_util::PathExists(FilePath(FLAGS_pppd_plugin))) { | |
| 44 LOG(WARNING) << "pppd_plugin (" << FLAGS_pppd_plugin << ") does not exist."; | |
| 45 } | |
| 46 return true; | |
| 47 } | |
| 48 | |
| 49 static void AddString(std::string* config, const char* key, | |
| 50 const std::string& value) { | |
| 51 config->append(StringPrintf("%s = %s\n", key, value.c_str())); | |
| 52 } | |
| 53 | |
| 54 static void AddBool(std::string* config, const char* key, bool value) { | |
| 55 config->append(StringPrintf("%s = %s\n", key, value ? "yes" : "no")); | |
| 56 } | |
| 57 | |
| 58 std::string L2tpManager::FormatL2tpdConfiguration( | |
| 59 const std::string& ppp_config_path) { | |
| 60 std::string l2tpd_config; | |
| 61 l2tpd_config.append(StringPrintf("[lac %s]\n", kL2tpConnectionName)); | |
| 62 AddString(&l2tpd_config, "lns", remote_); | |
| 63 AddBool(&l2tpd_config, "require chap", FLAGS_require_chap); | |
| 64 AddBool(&l2tpd_config, "refuse pap", FLAGS_refuse_pap); | |
| 65 AddBool(&l2tpd_config, "require authentication", | |
| 66 FLAGS_require_authentication); | |
| 67 AddString(&l2tpd_config, "name", FLAGS_user); | |
| 68 AddBool(&l2tpd_config, "ppp debug", FLAGS_ppp_debug); | |
| 69 AddString(&l2tpd_config, "pppoptfile", ppp_config_path); | |
| 70 AddBool(&l2tpd_config, "length bit", FLAGS_length_bit); | |
| 71 return l2tpd_config; | |
| 72 } | |
| 73 | |
| 74 std::string L2tpManager::FormatPppdConfiguration() { | |
| 75 std::string pppd_config = StringPrintf( | |
| 76 "ipcp-accept-local\n" | |
| 77 "ipcp-accept-remote\n" | |
| 78 "refuse-eap\n" | |
| 79 "noccp\n" | |
| 80 "noauth\n" | |
| 81 "crtscts\n" | |
| 82 "idle 1800\n" | |
| 83 "mtu 1410\n" | |
| 84 "mru 1410\n" | |
| 85 "nodefaultroute\n" | |
| 86 "debug\n" | |
| 87 "lock\n" | |
| 88 "connect-delay 5000\n"); | |
| 89 if (!FLAGS_pppd_plugin.empty()) { | |
| 90 DLOG(INFO) << "Using pppd plugin " << FLAGS_pppd_plugin; | |
| 91 pppd_config.append(StringPrintf("plugin %s\n", FLAGS_pppd_plugin.c_str())); | |
| 92 } | |
| 93 return pppd_config; | |
| 94 } | |
| 95 | |
| 96 bool L2tpManager::Initiate() { | |
| 97 std::string control_string; | |
| 98 control_string = StringPrintf("c %s", kL2tpConnectionName); | |
| 99 if (FLAGS_pppd_plugin.empty()) { | |
| 100 control_string.append(StringPrintf(" %s %s\n", | |
| 101 FLAGS_user.c_str(), | |
| 102 FLAGS_password.c_str())); | |
| 103 } else { | |
| 104 // otherwise the plugin must specify username and password. | |
| 105 control_string.append("\n"); | |
| 106 } | |
| 107 if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), | |
| 108 control_string.size())) { | |
| 109 return false; | |
| 110 } | |
| 111 return true; | |
| 112 } | |
| 113 | |
| 114 bool L2tpManager::Terminate() { | |
| 115 std::string control_string = StringPrintf("d %s\n", | |
| 116 kL2tpConnectionName); | |
| 117 if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), | |
| 118 control_string.size())) { | |
| 119 return false; | |
| 120 } | |
| 121 return true; | |
| 122 } | |
| 123 | |
| 124 bool L2tpManager::Start() { | |
| 125 FilePath pppd_config_path = temp_path_.Append("pppd.conf"); | |
| 126 std::string l2tpd_config = FormatL2tpdConfiguration(pppd_config_path.value()); | |
| 127 FilePath l2tpd_config_path = temp_path_.Append("l2tpd.conf"); | |
| 128 if (!file_util::WriteFile(l2tpd_config_path, l2tpd_config.c_str(), | |
| 129 l2tpd_config.size())) { | |
| 130 LOG(ERROR) << "Unable to write l2tpd config to " | |
| 131 << l2tpd_config_path.value(); | |
| 132 return false; | |
| 133 } | |
| 134 std::string pppd_config = FormatPppdConfiguration(); | |
| 135 if (!file_util::WriteFile(pppd_config_path, pppd_config.c_str(), | |
| 136 pppd_config.size())) { | |
| 137 LOG(ERROR) << "Unable to write pppd config to " << pppd_config_path.value(); | |
| 138 return false; | |
| 139 } | |
| 140 l2tpd_control_path_ = temp_path_.Append("l2tpd.control"); | |
| 141 file_util::Delete(l2tpd_control_path_, false); | |
| 142 l2tpd_->Reset(0); | |
| 143 l2tpd_->AddArg(L2TPD); | |
| 144 l2tpd_->AddStringOption("-c", l2tpd_config_path.value()); | |
| 145 l2tpd_->AddStringOption("-C", l2tpd_control_path_.value()); | |
| 146 l2tpd_->AddArg("-D"); | |
| 147 l2tpd_->RedirectUsingPipe(STDERR_FILENO, false); | |
| 148 l2tpd_->Start(); | |
| 149 output_fd_ = l2tpd_->GetPipe(STDERR_FILENO); | |
| 150 // 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.
| |
| 151 sleep(1); | |
| 152 bool result = Initiate(); | |
| 153 start_ticks_ = base::TimeTicks::Now(); | |
| 154 return result; | |
| 155 } | |
| 156 | |
| 157 // TODO: unit test this | |
| 158 int L2tpManager::Poll() { | |
| 159 if (is_running()) return -1; | |
| 160 if (start_ticks_.is_null()) return -1; | |
| 161 if (!file_util::PathExists(FilePath(kPppInterfacePath))) { | |
| 162 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
| |
| 163 FLAGS_authentication_timeout) { | |
| 164 LOG(ERROR) << "PPP authentication timed out."; | |
| 165 Terminate(); | |
| 166 OnStopped(false); | |
| 167 // 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.
| |
| 168 } | |
| 169 return 1000; | |
| 170 } | |
| 171 LOG(INFO) << "L2TP connection now up"; | |
| 172 OnStarted(); | |
| 173 return -1; | |
| 174 } | |
| 175 | |
| 176 void L2tpManager::HandleChild(pid_t pid, int signal) { | |
| 177 if (pid != l2tpd_->pid()) return; | |
| 178 | |
| 179 LOG(INFO) << "L2TP layer stopped"; | |
| 180 OnStopped(true); | |
| 181 } | |
| 182 | |
| 183 void L2tpManager::Stop() { | |
| 184 if (l2tpd_->pid()) { | |
| 185 LOG(INFO) << "Shutting down L2TP"; | |
| 186 Terminate(); | |
| 187 } | |
| 188 OnStopped(false); | |
| 189 } | |
| OLD | NEW |