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(ppp_setup_timeout, 10, "timeout to setup ppp (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"; | |
Will Drewry
2011/03/05 04:06:39
nice!
kmixter1
2011/03/11 01:34:27
Done.
| |
27 | |
28 using ::chromeos::ProcessImpl; | |
29 | |
30 L2tpManager::L2tpManager() | |
31 : ServiceManager("l2tp"), | |
32 was_initiated_(false), | |
33 output_fd_(-1), | |
34 ppp_interface_path_(kPppInterfacePath), | |
35 l2tpd_(new ProcessImpl) { | |
36 } | |
37 | |
38 bool L2tpManager::Initialize(const std::string& remote) { | |
39 remote_ = remote; | |
40 if (FLAGS_user.empty()) { | |
41 LOG(ERROR) << "l2tp layer requires user name"; | |
42 return false; | |
43 } | |
44 if (!FLAGS_pppd_plugin.empty() && | |
45 !file_util::PathExists(FilePath(FLAGS_pppd_plugin))) { | |
46 LOG(WARNING) << "pppd_plugin (" << FLAGS_pppd_plugin << ") does not exist."; | |
47 } | |
48 return true; | |
49 } | |
50 | |
51 static void AddString(std::string* config, const char* key, | |
52 const std::string& value) { | |
53 config->append(StringPrintf("%s = %s\n", key, value.c_str())); | |
54 } | |
55 | |
56 static void AddBool(std::string* config, const char* key, bool value) { | |
57 config->append(StringPrintf("%s = %s\n", key, value ? "yes" : "no")); | |
58 } | |
59 | |
60 std::string L2tpManager::FormatL2tpdConfiguration( | |
61 const std::string& ppp_config_path) { | |
62 std::string l2tpd_config; | |
63 l2tpd_config.append(StringPrintf("[lac %s]\n", kL2tpConnectionName)); | |
64 AddString(&l2tpd_config, "lns", remote_); | |
65 AddBool(&l2tpd_config, "require chap", FLAGS_require_chap); | |
66 AddBool(&l2tpd_config, "refuse pap", FLAGS_refuse_pap); | |
67 AddBool(&l2tpd_config, "require authentication", | |
68 FLAGS_require_authentication); | |
69 AddString(&l2tpd_config, "name", FLAGS_user); | |
70 AddBool(&l2tpd_config, "ppp debug", FLAGS_ppp_debug); | |
71 AddString(&l2tpd_config, "pppoptfile", ppp_config_path); | |
72 AddBool(&l2tpd_config, "length bit", FLAGS_length_bit); | |
73 return l2tpd_config; | |
74 } | |
75 | |
76 std::string L2tpManager::FormatPppdConfiguration() { | |
77 std::string pppd_config = StringPrintf( | |
78 "ipcp-accept-local\n" | |
79 "ipcp-accept-remote\n" | |
80 "refuse-eap\n" | |
81 "noccp\n" | |
82 "noauth\n" | |
83 "crtscts\n" | |
84 "idle 1800\n" | |
85 "mtu 1410\n" | |
86 "mru 1410\n" | |
87 "nodefaultroute\n" | |
88 "debug\n" | |
89 "lock\n" | |
90 "connect-delay 5000\n"); | |
91 if (!FLAGS_pppd_plugin.empty()) { | |
92 DLOG(INFO) << "Using pppd plugin " << FLAGS_pppd_plugin; | |
93 pppd_config.append(StringPrintf("plugin %s\n", FLAGS_pppd_plugin.c_str())); | |
94 } | |
95 return pppd_config; | |
96 } | |
97 | |
98 bool L2tpManager::Initiate() { | |
99 std::string control_string; | |
100 control_string = StringPrintf("c %s", kL2tpConnectionName); | |
101 if (FLAGS_pppd_plugin.empty()) { | |
102 control_string.append(StringPrintf(" %s %s\n", | |
103 FLAGS_user.c_str(), | |
104 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.
| |
105 } else { | |
106 // otherwise the plugin must specify username and password. | |
107 control_string.append("\n"); | |
108 } | |
109 if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), | |
110 control_string.size())) { | |
111 return false; | |
112 } | |
113 was_initiated_ = true; | |
114 return true; | |
115 } | |
116 | |
117 bool L2tpManager::Terminate() { | |
118 std::string control_string = StringPrintf("d %s\n", | |
119 kL2tpConnectionName); | |
120 if (!file_util::WriteFile(l2tpd_control_path_, control_string.c_str(), | |
121 control_string.size())) { | |
122 return false; | |
123 } | |
124 return true; | |
125 } | |
126 | |
127 bool L2tpManager::Start() { | |
128 FilePath pppd_config_path = temp_path_->Append("pppd.conf"); | |
129 std::string l2tpd_config = FormatL2tpdConfiguration(pppd_config_path.value()); | |
130 FilePath l2tpd_config_path = temp_path_->Append("l2tpd.conf"); | |
131 if (!file_util::WriteFile(l2tpd_config_path, l2tpd_config.c_str(), | |
132 l2tpd_config.size())) { | |
133 LOG(ERROR) << "Unable to write l2tpd config to " | |
134 << l2tpd_config_path.value(); | |
135 return false; | |
136 } | |
137 std::string pppd_config = FormatPppdConfiguration(); | |
138 if (!file_util::WriteFile(pppd_config_path, pppd_config.c_str(), | |
139 pppd_config.size())) { | |
140 LOG(ERROR) << "Unable to write pppd config to " << pppd_config_path.value(); | |
141 return false; | |
142 } | |
143 l2tpd_control_path_ = temp_path_->Append("l2tpd.control"); | |
144 file_util::Delete(l2tpd_control_path_, false); | |
145 | |
146 l2tpd_->Reset(0); | |
147 l2tpd_->AddArg(L2TPD); | |
148 l2tpd_->AddStringOption("-c", l2tpd_config_path.value()); | |
149 l2tpd_->AddStringOption("-C", l2tpd_control_path_.value()); | |
150 l2tpd_->AddArg("-D"); | |
151 l2tpd_->RedirectUsingPipe(STDERR_FILENO, false); | |
152 l2tpd_->Start(); | |
153 output_fd_ = l2tpd_->GetPipe(STDERR_FILENO); | |
154 start_ticks_ = base::TimeTicks::Now(); | |
155 return true; | |
156 } | |
157 | |
158 int L2tpManager::Poll() { | |
159 if (is_running()) return -1; | |
160 if (start_ticks_.is_null()) return -1; | |
161 if (!was_initiated_ && file_util::PathExists(l2tpd_control_path_)) { | |
162 if (!Initiate()) { | |
163 LOG(ERROR) << "Unable to initiate connection"; | |
164 Terminate(); | |
165 OnStopped(false); | |
166 return -1; | |
167 } | |
168 // With the connection initated, check if it's up in 1s. | |
169 return 1000; | |
170 } | |
171 if (was_initiated_ && file_util::PathExists(FilePath(ppp_interface_path_))) { | |
172 LOG(INFO) << "L2TP connection now up"; | |
173 OnStarted(); | |
174 return -1; | |
175 } | |
176 // Check for the ppp setup timeout. This includes the time | |
177 // to start pppd, it to set up its control file, l2tp connection | |
178 // setup, ppp connection setup. Authentication happens after | |
179 // the ppp device is created. | |
180 if (base::TimeTicks::Now() - start_ticks_ > | |
181 base::TimeDelta::FromSeconds(FLAGS_ppp_setup_timeout)) { | |
182 LOG(ERROR) << "PPP setup timed out"; | |
183 // Cleanly terminate if the control file exists. | |
184 if (was_initiated_) Terminate(); | |
185 OnStopped(false); | |
186 // Poll in 1 second in order to check if clean shutdown worked. | |
187 } | |
188 return 1000; | |
189 } | |
190 | |
191 void L2tpManager::ProcessOutput() { | |
192 ServiceManager::WriteFdToSyslog(output_fd_, ""); | |
193 } | |
194 | |
195 bool L2tpManager::IsChild(pid_t pid) { | |
196 return pid == l2tpd_->pid(); | |
197 } | |
198 | |
199 void L2tpManager::Stop() { | |
200 if (l2tpd_->pid()) { | |
201 LOG(INFO) << "Shutting down L2TP"; | |
202 Terminate(); | |
203 } | |
204 OnStopped(false); | |
205 } | |
OLD | NEW |