BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 include_guard "pppoe"
2  
3 template pppoe {
4 alias("_arg0") dev;
5 alias("_arg1") username;
6 alias("_arg2") password;
7 alias("_arg3") pre_up_template;
8  
9 # Choose which NCD interpreter will be used for the pppd event scripts.
10 var("/usr/local/badvpn/bin/badvpn-ncd") ncd_interpreter_path;
11  
12 # Retry point here.
13 var("false") retrying;
14 backtrack_point() retry_point;
15 If (retrying) {
16 sleep("5000");
17 };
18 retrying->set("true");
19  
20 # Create a temporary directory.
21 concat("/run/ncd-pppoe-", dev) run_dir;
22 run({"/bin/rm", "-rf", run_dir}, {});
23 run({"/bin/mkdir", run_dir}, {"/bin/rm", "-rf", run_dir});
24  
25 # Build paths for pppd scripts and other files.
26 concat(run_dir, "/ncd-request.socket") socket_path;
27 concat(run_dir, "/pppoe.pid") pppoe_pid_path;
28 concat(run_dir, "/pap-secrets") pap_secrets_path;
29 concat(run_dir, "/chap-secrets") chap_secrets_path;
30 concat(run_dir, "/pppd2.tdb") pppdb_path;
31 concat(run_dir, "/resolv.conf") resolv_conf_path;
32 concat(run_dir, "/script-auth-up") path_auth_up;
33 concat(run_dir, "/script-auth-down") path_auth_down;
34 concat(run_dir, "/script-auth-fail") path_auth_fail;
35 concat(run_dir, "/script-ip-pre-up") path_ip_pre_up;
36 concat(run_dir, "/script-ip-up") path_ip_up;
37 concat(run_dir, "/script-ip-down") path_ip_down;
38 concat(run_dir, "/script-ipv6-up") path_ipv6_up;
39 concat(run_dir, "/script-ipv6-down") path_ipv6_down;
40 concat(run_dir, "/script-ipx-up") path_ipx_up;
41 concat(run_dir, "/script-ipx-down") path_ipx_down;
42  
43 # Write secrets files.
44 call("pppoe__write_secrets", {pap_secrets_path, username, password});
45 call("pppoe__write_secrets", {chap_secrets_path, username, password});
46  
47 # Write pppd scripts. These will contact us via the request socket.
48 call("pppoe__write_script", {"ip-pre-up", path_ip_pre_up});
49 call("pppoe__write_script", {"ip-up", path_ip_up});
50 call("pppoe__write_script", {"ip-down", path_ip_down});
51  
52 # Build path arguments for pppd;
53 concat("pid-dir=", run_dir) arg_pid_dir;
54 concat("pap-secrets=", pap_secrets_path) arg_pap_secrets;
55 concat("chap-secrets=", chap_secrets_path) arg_chap_secrets;
56 concat("pppdb=", pppdb_path) arg_pppdb;
57 concat("resolv.conf=", resolv_conf_path) arg_resolv_conf;
58 concat("auth-up=", path_auth_up) arg_auth_up;
59 concat("auth-down=", path_auth_down) arg_auth_down;
60 concat("auth-fail=", path_auth_fail) arg_auth_fail;
61 concat("ip-pre-up=", path_ip_pre_up) arg_ip_pre_up;
62 concat("ip-up=", path_ip_up) arg_ip_up;
63 concat("ip-down=", path_ip_down) arg_ip_down;
64 concat("ipv6-up=", path_ipv6_up) arg_ipv6_up;
65 concat("ipv6-down=", path_ipv6_down) arg_ipv6_down;
66 concat("ipx-up=", path_ipx_up) arg_ipx_up;
67 concat("ipx-down=", path_ipx_down) arg_ipx_down;
68  
69 # Create state variables and blockers. When the request server
70 # receives requests it will update those variables and blockers.
71 var("down") state;
72 var("") current_ifname;
73 var("") current_local_ip;
74 var("") current_remote_ip;
75 value({}) current_dns_servers;
76 blocker() ip_pre_up_blocker;
77 blocker() ip_pre_up_done_blocker;
78 blocker() ip_up_blocker;
79  
80 # Start request server.
81 sys.request_server({"unix", socket_path}, "pppoe__request_handler", {});
82  
83 # Start pppd.
84 sys.start_process({
85 "/usr/sbin/pppd", "nodetach", "plugin", "rp-pppoe.so", dev, "noipdefault", "hide-password",
86 "usepeerdns", "user", username,
87 "path", arg_pid_dir, "path", arg_pap_secrets, "path", arg_chap_secrets, "path", arg_pppdb,
88 "path", arg_resolv_conf,
89 "path", arg_auth_up, "path", arg_auth_down, "path", arg_auth_fail, "path", arg_ip_pre_up,
90 "path", arg_ip_up, "path", arg_ip_down, "path", arg_ipv6_up, "path", arg_ipv6_down,
91 "path", arg_ipx_up, "path", arg_ipx_down
92 }, "", ["deinit_kill_time":"2000"]) pppd;
93  
94 # Start a process which will cause retrying when pppd dies.
95 spawn("pppoe__pppd_wait", {});
96  
97 # Wait for ip-pre-up.
98 ip_pre_up_blocker->use();
99  
100 # Grab the current state variables, so the user doesn't
101 # see any unexpected changes.
102 var(current_ifname) ifname;
103 var(current_local_ip) local_ip;
104 var(current_remote_ip) remote_ip;
105 var(current_dns_servers) dns_servers;
106  
107 # Call pre-up callback template.
108 call_with_caller_target(pre_up_template, {ifname, local_ip, remote_ip, dns_servers}, "_caller");
109  
110 # Allow pre-up script to terminate.
111 ip_pre_up_done_blocker->up();
112  
113 # Wait for connection to go up.
114 ip_up_blocker->use();
115 }
116  
117 template pppoe__pppd_wait {
118 # Wait for pppd to die.
119 _caller.pppd->wait();
120  
121 # Retry.
122 _caller.retry_point->go();
123 }
124  
125 template pppoe__write_secrets {
126 alias("_arg0") file_path;
127 alias("_arg1") username;
128 alias("_arg2") password;
129  
130 # Escape username and password.
131 regex_replace(username, {"\""}, {"\\\""}) username_esc;
132 regex_replace(password, {"\""}, {"\\\""}) password_esc;
133  
134 # Write empty file and chmod it.
135 file_write(file_path, "");
136 run({"/bin/chmod", "600", file_path}, {});
137  
138 # Build contents.
139 concat("\"", username_esc, "\" * \"", password_esc, "\"\n") contents;
140  
141 # Write file.
142 file_write(file_path, contents);
143 }
144  
145 template pppoe__write_script {
146 alias("_arg0") event;
147 alias("_arg1") script_path;
148  
149 # This string is an NCD script which will be run by pppd.
150 # When run, it will contact us via the request server,
151 # and the requests will be processed in pppoe__request_handler.
152 var("#!<NCD_INTERPRETER_PATH>
153  
154 process main {
155 # Hardcoded strings.
156 var(\"<EVENT>\") hardcoded_event;
157 var(\"<SOCKET>\") hardcoded_socket;
158  
159 # Start timeout to kill us after some time if we don't manage
160 # to contact the server.
161 spawn(\"timeout_process\", {});
162  
163 # Build event data map.
164 getargs() args;
165 value([\"EVENT\":hardcoded_event, \"ARGS\":args]) msg_map;
166 var({\"DEVICE\", \"IFNAME\", \"IPLOCAL\", \"IPREMOTE\", \"PEERNAME\", \"LOCALNAME\",
167 \"SPEED\", \"ORIG_UID\", \"PPPLOGNAME\", \"CONNECT_TIME\", \"BYTES_SENT\",
168 \"BYTES_RCVD\", \"LINKNAME\", \"DNS1\", \"DNS2\", \"WINS1\", \"WINS2\"}) var_names;
169 Foreach (var_names As var_name) {
170 getenv(var_name) env;
171 If (env.exists) {
172 msg_map->insert(var_name, env);
173 };
174 };
175  
176 # Connect to socket.
177 sys.request_client({\"unix\", hardcoded_socket}) client;
178  
179 # Send request.
180 client->request(msg_map, \"reply_handler\", \"finished_handler\", {});
181 }
182  
183 template reply_handler {
184 print();
185 }
186  
187 template finished_handler {
188 # Request was received by server, exit now.
189 exit(\"0\");
190 }
191  
192 template timeout_process {
193 # Sleep some time.
194 sleep(\"5000\");
195 # Timed out, exit now.
196 exit(\"1\");
197 }
198  
199 " ) script_contents_template;
200  
201 # Replace some constants in the script with the right values.
202 regex_replace(script_contents_template,
203 {"<NCD_INTERPRETER_PATH>", "<EVENT>", "<SOCKET>"},
204 {_caller.ncd_interpreter_path, event, _caller.socket_path}
205 ) script_contents;
206  
207 # Write the script.
208 file_write(script_path, script_contents);
209  
210 # Make it executable.
211 run({"/bin/chmod", "+x", script_path}, {});
212 }
213  
214 template pppoe__request_handler {
215 alias("_caller") pppoe;
216  
217 # Get event type from request.
218 value(_request.data) request;
219 request->get("EVENT") event;
220  
221 # Match to known types.
222 val_equal(event, "ip-down") is_ip_down;
223 val_equal(event, "ip-pre-up") is_ip_pre_up;
224 val_equal(event, "ip-up") is_ip_up;
225  
226 If (is_ip_down) {
227 # Set state.
228 pppoe.state->set("down");
229  
230 # Set blockers down.
231 pppoe.ip_up_blocker->down();
232 pppoe.ip_pre_up_done_blocker->down();
233 pppoe.ip_pre_up_blocker->down();
234 }
235 Elif (is_ip_pre_up) {
236 # Expecting to be in "down" state here.
237 val_different(pppoe.state, "down") state_is_wrong;
238 If (state_is_wrong) {
239 pppoe.retry_point->go();
240 _request->finish();
241 };
242  
243 # Get variables from request.
244 request->get("IFNAME") ifname;
245 request->get("IPLOCAL") local_ip;
246 request->get("IPREMOTE") remote_ip;
247 request->try_get("DNS1") dns1;
248 request->try_get("DNS2") dns2;
249  
250 # Write variables.
251 pppoe.current_ifname->set(ifname);
252 pppoe.current_local_ip->set(local_ip);
253 pppoe.current_remote_ip->set(remote_ip);
254 pppoe.current_dns_servers->reset({});
255 If (dns1.exists) {
256 pppoe.current_dns_servers->insert(pppoe.current_dns_servers.length, dns1);
257 };
258 If (dns2.exists) {
259 pppoe.current_dns_servers->insert(pppoe.current_dns_servers.length, dns2);
260 };
261  
262 # Set state.
263 pppoe.state->set("pre-up");
264  
265 # Set ip-pre-up blocker up.
266 pppoe.ip_pre_up_blocker->up();
267  
268 # Wait for pre-up to be finished. This causes the script contacting
269 # us to not return until then, and effectively delays pppd in setting
270 # the device up and calling the ip-up script.
271 pppoe.ip_pre_up_done_blocker->use();
272 }
273 Elif(is_ip_up) {
274 # Expecting to be in "pre-up" state here.
275 val_different(pppoe.state, "pre-up") state_is_wrong;
276 If (state_is_wrong) {
277 pppoe.retry_point->go();
278 _request->finish();
279 };
280  
281 # Set state.
282 pppoe.state->set("up");
283  
284 # Set ip-up blocker up.
285 pppoe.ip_up_blocker->up();
286 };
287  
288 # Finish request.
289 _request->finish();
290 }
291  
292 template pppoe__escapeshellarg {
293 alias("_arg0") input;
294 regex_replace(input, {"'"}, {"\\'"}) replaced;
295 concat("'", replaced, "'") result;
296 }