Project

General

Profile

Download (52 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	openvpn.inc
4

    
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (C) 2006  Fernando Lemos
7
	Copyright (c) 2006-2016 Electric Sheep Fencing, LLC.
8
	All rights reserved.
9

    
10
	This file was rewritten from scratch by Fernando Lemos but
11
	*MIGHT* contain code previously written by:
12

    
13
	Copyright (C) 2005 Peter Allgeyer <allgeyer_AT_web.de>
14
	All rights reserved.
15

    
16
	Copyright (C) 2004 Peter Curran (peter@closeconsultants.com).
17
	All rights reserved.
18

    
19
	Redistribution and use in source and binary forms, with or without
20
	modification, are permitted provided that the following conditions are met:
21

    
22
	1. Redistributions of source code must retain the above copyright notice,
23
	   this list of conditions and the following disclaimer.
24

    
25
	2. Redistributions in binary form must reproduce the above copyright
26
	   notice, this list of conditions and the following disclaimer in
27
	   the documentation and/or other materials provided with the
28
	   distribution.
29

    
30
	3. All advertising materials mentioning features or use of this software
31
	   must display the following acknowledgment:
32
	   "This product includes software developed by the pfSense Project
33
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
34

    
35
	4. The names "pfSense" and "pfSense Project" must not be used to
36
	   endorse or promote products derived from this software without
37
	   prior written permission. For written permission, please contact
38
	   coreteam@pfsense.org.
39

    
40
	5. Products derived from this software may not be called "pfSense"
41
	   nor may "pfSense" appear in their names without prior written
42
	   permission of the Electric Sheep Fencing, LLC.
43

    
44
	6. Redistributions of any form whatsoever must retain the following
45
	   acknowledgment:
46

    
47
	"This product includes software developed by the pfSense Project
48
	for use in the pfSense software distribution (http://www.pfsense.org/).
49

    
50
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
51
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
54
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61
	OF THE POSSIBILITY OF SUCH DAMAGE.
62
*/
63

    
64
require_once('config.inc');
65
require_once("certs.inc");
66
require_once('pfsense-utils.inc');
67
require_once("auth.inc");
68

    
69
global $openvpn_prots;
70
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
71

    
72
global $openvpn_dev_mode;
73
$openvpn_dev_mode = array("tun", "tap");
74

    
75
global $openvpn_verbosity_level;
76
$openvpn_verbosity_level = array(
77
	0 =>	gettext("none"),
78
	1 =>	gettext("default"),
79
	2 =>	"2",
80
	3 =>	gettext("3 (recommended)"),
81
	4 =>	"4",
82
	5 => 	"5",
83
	6 => 	"6",
84
	7 => 	"7",
85
	8 => 	"8",
86
	9 => 	"9",
87
	10 => 	"10",
88
	11 => 	"11"
89
);
90

    
91
/*
92
 * The User Auth mode below is disabled because
93
 * OpenVPN erroneously requires that we provide
94
 * a CA configuration parameter. In this mode,
95
 * clients don't send a certificate so there is
96
 * no need for a CA. If we require that admins
97
 * provide one in the pfSense UI due to a bogus
98
 * requirement imposed by OpenVPN, it could be
99
 * considered very confusing ( I know I was ).
100
 *
101
 * -mgrooms
102
 */
103

    
104
global $openvpn_dh_lengths;
105
$openvpn_dh_lengths = array(
106
	1024, 2048, 3072, 4096, 7680, 8192, 15360, 16384
107
);
108

    
109
global $openvpn_cert_depths;
110
$openvpn_cert_depths = array(
111
	1 => gettext("One (Client+Server)"),
112
	2 => gettext("Two (Client+Intermediate+Server)"),
113
	3 => gettext("Three (Client+2xIntermediate+Server)"),
114
	4 => gettext("Four (Client+3xIntermediate+Server)"),
115
	5 => gettext("Five (Client+4xIntermediate+Server)")
116
);
117

    
118
global $openvpn_server_modes;
119
$openvpn_server_modes = array(
120
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
121
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"),
122
	'server_tls' => gettext("Remote Access ( SSL/TLS )"),
123
	'server_user' => gettext("Remote Access ( User Auth )"),
124
	'server_tls_user' => gettext("Remote Access ( SSL/TLS + User Auth )"));
125

    
126
global $openvpn_tls_server_modes;
127
$openvpn_tls_server_modes = array('p2p_tls', 'server_tls', 'server_user', 'server_tls_user');
128

    
129
global $openvpn_client_modes;
130
$openvpn_client_modes = array(
131
	'p2p_tls' => gettext("Peer to Peer ( SSL/TLS )"),
132
	'p2p_shared_key' => gettext("Peer to Peer ( Shared Key )"));
133

    
134
global $openvpn_compression_modes;
135
$openvpn_compression_modes = array(
136
	'' => gettext("No Preference"),
137
	'no' => gettext("Disabled - No Compression"),
138
	'adaptive' => gettext("Enabled with Adaptive Compression"),
139
	'yes' => gettext("Enabled without Adaptive Compression"));
140

    
141
global $openvpn_topologies;
142
$openvpn_topologies = array(
143
	'subnet' => gettext("Subnet -- One IP address per client in a common subnet"),
144
	'net30' => gettext("net30 -- Isolated /30 network per client")
145
//	'p2p => gettext("Peer to Peer -- One IP address per client peer-to-peer style. Does not work on Windows.")
146
);
147

    
148
function openvpn_build_mode_list() {
149
	global $openvpn_server_modes;
150

    
151
	$list = array();
152

    
153
	foreach ($openvpn_server_modes as $name => $desc) {
154
		$list[$name] = $desc;
155
	}
156

    
157
	return($list);
158
}
159

    
160
function openvpn_build_if_list() {
161
	$list = array();
162

    
163
	$interfaces = get_configured_interface_with_descr();
164
	$viplist = get_configured_vip_list();
165
	foreach ($viplist as $vip => $address) {
166
		$interfaces[$vip.'|'.$address] = $address;
167
		if (get_vip_descr($address)) {
168
			$interfaces[$vip.'|'.$address] .= " (";
169
			$interfaces[$vip.'|'.$address] .= get_vip_descr($address);
170
			$interfaces[$vip.'|'.$address] .= ")";
171
		}
172
	}
173

    
174
	$grouplist = return_gateway_groups_array();
175
	foreach ($grouplist as $name => $group) {
176
		if ($group[0]['vip'] != "") {
177
			$vipif = $group[0]['vip'];
178
		} else {
179
			$vipif = $group[0]['int'];
180
		}
181

    
182
		$interfaces[$name] = "GW Group {$name}";
183
	}
184

    
185
	$interfaces['lo0'] = "Localhost";
186
	$interfaces['any'] = "any";
187

    
188
	foreach ($interfaces as $iface => $ifacename) {
189
	   $list[$iface] = $ifacename;
190
	}
191

    
192
	return($list);
193
}
194

    
195
function openvpn_build_crl_list() {
196
	global $a_crl;
197

    
198
	$list = array('' => 'None');
199

    
200
	foreach ($a_crl as $crl) {
201
		$caname = "";
202
		$ca = lookup_ca($crl['caref']);
203

    
204
		if ($ca) {
205
			$caname = " (CA: {$ca['descr']})";
206
		}
207

    
208
		$list[$crl['refid']] = $crl['descr'] . $caname;
209
	}
210

    
211
	return($list);
212
}
213

    
214
function openvpn_build_cert_list($include_none = false, $prioritize_server_certs = false) {
215
	global $a_cert;
216

    
217
	if ($include_none) {
218
		$list = array('' => gettext('None (Username and/or Password required)'));
219
	} else {
220
		$list = array();
221
	}
222

    
223
	$non_server_list = array();
224

    
225
	if ($prioritize_server_certs) {
226
		$list[' '] = gettext("===== Server Certificates =====");
227
		$non_server_list['  '] = gettext("===== Non-Server Certificates =====");
228
	}
229

    
230
	foreach ($a_cert as $cert) {
231
		$properties = array();
232
		$propstr = "";
233
		$ca = lookup_ca($cert['caref']);
234
		$purpose = cert_get_purpose($cert['crt'], true);
235

    
236
		if ($purpose['server'] == "Yes") {
237
			$properties[] = gettext("Server: Yes");
238
		} elseif ($prioritize_server_certs) {
239
			$properties[] = gettext("Server: NO");
240
		}
241
		if ($ca) {
242
			$properties[] = sprintf(gettext("CA: %s"), $ca['descr']);
243
		}
244
		if (cert_in_use($cert['refid'])) {
245
			$properties[] = gettext("In Use");
246
		}
247
		if (is_cert_revoked($cert)) {
248
			$properties[] = gettext("Revoked");
249
		}
250

    
251
		if (!empty($properties)) {
252
			$propstr = " (" . implode(", ", $properties) . ")";
253
		}
254

    
255
		if ($prioritize_server_certs) {
256
			if ($purpose['server'] == "Yes") {
257
				$list[$cert['refid']] = $cert['descr'] . $propstr;
258
			} else {
259
				$non_server_list[$cert['refid']] = $cert['descr'] . $propstr;
260
			}
261
		} else {
262
			$list[$cert['refid']] = $cert['descr'] . $propstr;
263
		}
264
	}
265

    
266
	return(array('server' => $list, 'non-server' => $non_server_list));
267
}
268

    
269
function openvpn_build_bridge_list() {
270
	$list = array();
271

    
272
	$serverbridge_interface['none'] = "none";
273
	$serverbridge_interface = array_merge($serverbridge_interface, get_configured_interface_with_descr());
274
	$viplist = get_configured_vip_list();
275

    
276
	foreach ($viplist as $vip => $address) {
277
		$serverbridge_interface[$vip.'|'.$address] = $address;
278
		if (get_vip_descr($address)) {
279
			$serverbridge_interface[$vip.'|'.$address] .= " (". get_vip_descr($address) .")";
280
		}
281
	}
282

    
283
	foreach ($serverbridge_interface as $iface => $ifacename) {
284
		$list[$iface] = htmlspecialchars($ifacename);
285
	}
286

    
287
	return($list);
288
}
289

    
290
function openvpn_create_key() {
291

    
292
	$fp = popen("/usr/local/sbin/openvpn --genkey --secret /dev/stdout 2>/dev/null", "r");
293
	if (!$fp) {
294
		return false;
295
	}
296

    
297
	$rslt = stream_get_contents($fp);
298
	pclose($fp);
299

    
300
	return $rslt;
301
}
302

    
303
function openvpn_create_dhparams($bits) {
304

    
305
	$fp = popen("/usr/bin/openssl dhparam {$bits} 2>/dev/null", "r");
306
	if (!$fp) {
307
		return false;
308
	}
309

    
310
	$rslt = stream_get_contents($fp);
311
	pclose($fp);
312

    
313
	return $rslt;
314
}
315

    
316
function openvpn_vpnid_used($vpnid) {
317
	global $config;
318

    
319
	if (is_array($config['openvpn']['openvpn-server'])) {
320
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
321
			if ($vpnid == $settings['vpnid']) {
322
				return true;
323
			}
324
		}
325
	}
326

    
327
	if (is_array($config['openvpn']['openvpn-client'])) {
328
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
329
			if ($vpnid == $settings['vpnid']) {
330
				return true;
331
			}
332
		}
333
	}
334

    
335
	return false;
336
}
337

    
338
function openvpn_vpnid_next() {
339

    
340
	$vpnid = 1;
341
	while (openvpn_vpnid_used($vpnid)) {
342
		$vpnid++;
343
	}
344

    
345
	return $vpnid;
346
}
347

    
348
function openvpn_port_used($prot, $interface, $port, $curvpnid = 0) {
349
	global $config;
350

    
351
	if (is_array($config['openvpn']['openvpn-server'])) {
352
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
353
			if (isset($settings['disable'])) {
354
				continue;
355
			}
356

    
357
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
358
				continue;
359
			}
360

    
361
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
362
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
363
				return $settings['vpnid'];
364
			}
365
		}
366
	}
367

    
368
	if (is_array($config['openvpn']['openvpn-client'])) {
369
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
370
			if (isset($settings['disable'])) {
371
				continue;
372
			}
373

    
374
			if ($curvpnid != 0 && $curvpnid == $settings['vpnid']) {
375
				continue;
376
			}
377

    
378
			if ($port == $settings['local_port'] && $prot == $settings['protocol'] &&
379
			    ($interface == $settings['interface'] || $interface == "any" || $settings['interface'] == "any")) {
380
				return $settings['vpnid'];
381
			}
382
		}
383
	}
384

    
385
	return 0;
386
}
387

    
388
function openvpn_port_next($prot, $interface = "wan") {
389

    
390
	$port = 1194;
391
	while (openvpn_port_used($prot, $interface, $port)) {
392
		$port++;
393
	}
394
	while (openvpn_port_used($prot, "any", $port)) {
395
		$port++;
396
	}
397

    
398
	return $port;
399
}
400

    
401
function openvpn_get_cipherlist() {
402

    
403
	$ciphers = array();
404
	$cipher_out = shell_exec('/usr/local/sbin/openvpn --show-ciphers | /usr/bin/grep "default key" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
405
	$cipher_lines = explode("\n", trim($cipher_out));
406
	sort($cipher_lines);
407
	foreach ($cipher_lines as $line) {
408
		$words = explode(' ', $line);
409
		$ciphers[$words[0]] = "{$words[0]} {$words[1]}";
410
	}
411
	$ciphers["none"] = gettext("None (No Encryption)");
412
	return $ciphers;
413
}
414

    
415
function openvpn_get_digestlist() {
416

    
417
	$digests = array();
418
	$digest_out = shell_exec('/usr/local/sbin/openvpn --show-digests | /usr/bin/grep "digest size" | /usr/bin/awk \'{print $1, "(" $2 "-" $3 ")";}\'');
419
	$digest_lines = explode("\n", trim($digest_out));
420
	sort($digest_lines);
421
	foreach ($digest_lines as $line) {
422
		$words = explode(' ', $line);
423
		$digests[$words[0]] = "{$words[0]} {$words[1]}";
424
	}
425
	$digests["none"] = gettext("None (No Authentication)");
426
	return $digests;
427
}
428

    
429
function openvpn_get_engines() {
430
	$openssl_engines = array('none' => gettext('No Hardware Crypto Acceleration'));
431
	exec("/usr/bin/openssl engine -t -c", $openssl_engine_output);
432
	$openssl_engine_output = implode("\n", $openssl_engine_output);
433
	$openssl_engine_output = preg_replace("/\\n\\s+/", "|", $openssl_engine_output);
434
	$openssl_engine_output = explode("\n", $openssl_engine_output);
435

    
436
	foreach ($openssl_engine_output as $oeo) {
437
		$keep = true;
438
		$details = explode("|", $oeo);
439
		$engine = array_shift($details);
440
		$linematch = array();
441
		preg_match("/\((.*)\)\s(.*)/", $engine, $linematch);
442
		foreach ($details as $dt) {
443
			if (strpos($dt, "unavailable") !== FALSE) {
444
				$keep = false;
445
			}
446
			if (strpos($dt, "available") !== FALSE) {
447
				continue;
448
			}
449
			if (strpos($dt, "[") !== FALSE) {
450
				$ciphers = trim($dt, "[]");
451
			}
452
		}
453
		if (!empty($ciphers)) {
454
			$ciphers = " - " . $ciphers;
455
		}
456
		if (strlen($ciphers) > 60) {
457
			$ciphers = substr($ciphers, 0, 60) . " ... ";
458
		}
459
		if ($keep) {
460
			$openssl_engines[$linematch[1]] = $linematch[2] . $ciphers;
461
		}
462
	}
463
	return $openssl_engines;
464
}
465

    
466
function openvpn_validate_engine($engine) {
467
	$engines = openvpn_get_engines();
468
	return array_key_exists($engine, $engines);
469
}
470

    
471
function openvpn_validate_host($value, $name) {
472
	$value = trim($value);
473
	if (empty($value) || (!is_domain($value) && !is_ipaddr($value))) {
474
		return sprintf(gettext("The field '%s' must contain a valid IP address or domain name."), $name);
475
	}
476
	return false;
477
}
478

    
479
function openvpn_validate_port($value, $name) {
480
	$value = trim($value);
481
	if (empty($value) || !is_numeric($value) || $value < 0 || ($value > 65535)) {
482
		return sprintf(gettext("The field '%s' must contain a valid port, ranging from 0 to 65535."), $name);
483
	}
484
	return false;
485
}
486

    
487
function openvpn_validate_cidr($value, $name, $multiple = false, $ipproto = "ipv4") {
488
	$value = trim($value);
489
	$error = false;
490
	if (empty($value)) {
491
		return false;
492
	}
493
	$networks = explode(',', $value);
494

    
495
	if (!$multiple && (count($networks) > 1)) {
496
		return sprintf(gettext("The field '%1\$s' must contain a single valid %2\$s CIDR range."), $name, $ipproto);
497
	}
498

    
499
	foreach ($networks as $network) {
500
		if ($ipproto == "ipv4") {
501
			$error = !openvpn_validate_cidr_ipv4($network);
502
		} else {
503
			$error = !openvpn_validate_cidr_ipv6($network);
504
		}
505
		if ($error) {
506
			break;
507
		}
508
	}
509

    
510
	if ($error) {
511
		return sprintf(gettext("The field '%1\$s' must contain only valid %2\$s CIDR range(s) separated by commas."), $name, $ipproto);
512
	} else {
513
		return false;
514
	}
515
}
516

    
517
function openvpn_validate_cidr_ipv4($value) {
518
	$value = trim($value);
519
	if (!empty($value)) {
520
		list($ip, $mask) = explode('/', $value);
521
		if (!is_ipaddrv4($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) {
522
			return false;
523
		}
524
	}
525
	return true;
526
}
527

    
528
function openvpn_validate_cidr_ipv6($value) {
529
	$value = trim($value);
530
	if (!empty($value)) {
531
		list($ipv6, $prefix) = explode('/', $value);
532
		if (empty($prefix)) {
533
			$prefix = "128";
534
		}
535
		if (!is_ipaddrv6($ipv6) or !is_numeric($prefix) or ($prefix > 128) or ($prefix < 0)) {
536
			return false;
537
		}
538
	}
539
	return true;
540
}
541

    
542
function openvpn_add_dhcpopts(& $settings, & $conf) {
543

    
544
	if (!empty($settings['dns_domain'])) {
545
		$conf .= "push \"dhcp-option DOMAIN {$settings['dns_domain']}\"\n";
546
	}
547

    
548
	if (!empty($settings['dns_server1'])) {
549
		$conf .= "push \"dhcp-option DNS {$settings['dns_server1']}\"\n";
550
	}
551
	if (!empty($settings['dns_server2'])) {
552
		$conf .= "push \"dhcp-option DNS {$settings['dns_server2']}\"\n";
553
	}
554
	if (!empty($settings['dns_server3'])) {
555
		$conf .= "push \"dhcp-option DNS {$settings['dns_server3']}\"\n";
556
	}
557
	if (!empty($settings['dns_server4'])) {
558
		$conf .= "push \"dhcp-option DNS {$settings['dns_server4']}\"\n";
559
	}
560

    
561
	if (!empty($settings['push_register_dns'])) {
562
		$conf .= "push \"register-dns\"\n";
563
	}
564

    
565
	if (!empty($settings['ntp_server1'])) {
566
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server1']}\"\n";
567
	}
568
	if (!empty($settings['ntp_server2'])) {
569
		$conf .= "push \"dhcp-option NTP {$settings['ntp_server2']}\"\n";
570
	}
571

    
572
	if ($settings['netbios_enable']) {
573

    
574
		if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) {
575
			$conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n";
576
		}
577
		if (!empty($settings['dhcp_nbtscope'])) {
578
			$conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n";
579
		}
580

    
581
		if (!empty($settings['wins_server1'])) {
582
			$conf .= "push \"dhcp-option WINS {$settings['wins_server1']}\"\n";
583
		}
584
		if (!empty($settings['wins_server2'])) {
585
			$conf .= "push \"dhcp-option WINS {$settings['wins_server2']}\"\n";
586
		}
587

    
588
		if (!empty($settings['nbdd_server1'])) {
589
			$conf .= "push \"dhcp-option NBDD {$settings['nbdd_server1']}\"\n";
590
		}
591
	}
592

    
593
	if ($settings['gwredir']) {
594
		$conf .= "push \"redirect-gateway def1\"\n";
595
	}
596
}
597

    
598
function openvpn_add_custom(& $settings, & $conf) {
599

    
600
	if ($settings['custom_options']) {
601

    
602
		$options = explode(';', $settings['custom_options']);
603

    
604
		if (is_array($options)) {
605
			foreach ($options as $option) {
606
				$conf .= "$option\n";
607
			}
608
		} else {
609
			$conf .= "{$settings['custom_options']}\n";
610
		}
611
	}
612
}
613

    
614
function openvpn_add_keyfile(& $data, & $conf, $mode_id, $directive, $opt = "") {
615
	global $g;
616

    
617
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.{$directive}";
618
	openvpn_create_dirs();
619
	file_put_contents($fpath, base64_decode($data));
620
	//chown($fpath, 'nobody');
621
	//chgrp($fpath, 'nobody');
622
	@chmod($fpath, 0600);
623

    
624
	$conf .= "{$directive} {$fpath} {$opt}\n";
625
}
626

    
627
function openvpn_reconfigure($mode, $settings) {
628
	global $g, $config, $openvpn_tls_server_modes;
629

    
630
	if (empty($settings)) {
631
		return;
632
	}
633
	if (isset($settings['disable'])) {
634
		return;
635
	}
636
	openvpn_create_dirs();
637
	/*
638
	 * NOTE: Deleting tap devices causes spontaneous reboots. Instead,
639
	 * we use a vpnid number which is allocated for a particular client
640
	 * or server configuration. ( see openvpn_vpnid_next() )
641
	 */
642

    
643
	$vpnid = $settings['vpnid'];
644
	$mode_id = $mode.$vpnid;
645

    
646
	if (isset($settings['dev_mode'])) {
647
		$tunname = "{$settings['dev_mode']}{$vpnid}";
648
	} else {
649
		/* defaults to tun */
650
		$tunname = "tun{$vpnid}";
651
		$settings['dev_mode'] = "tun";
652
	}
653

    
654
	if ($mode == "server") {
655
		$devname = "ovpns{$vpnid}";
656
	} else {
657
		$devname = "ovpnc{$vpnid}";
658
	}
659

    
660
	/* is our device already configured */
661
	if (!does_interface_exist($devname)) {
662

    
663
		/* create the tap device if required */
664
		if (!file_exists("/dev/{$tunname}")) {
665
			exec("/sbin/ifconfig " . escapeshellarg($tunname) . " create");
666
		}
667

    
668
		/* rename the device */
669
		mwexec("/sbin/ifconfig " . escapeshellarg($tunname) . " name " . escapeshellarg($devname));
670

    
671
		/* add the device to the openvpn group and make sure it's UP*/
672
		mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " group openvpn up");
673

    
674
		$ifname = convert_real_interface_to_friendly_interface_name($devname);
675
		$grouptmp = link_interface_to_group($ifname);
676
		if (!empty($grouptmp)) {
677
			array_walk($grouptmp, 'interface_group_add_member');
678
		}
679
		unset($grouptmp, $ifname);
680
	}
681

    
682
	$pfile = $g['varrun_path'] . "/openvpn_{$mode_id}.pid";
683
	$proto = strtolower($settings['protocol']);
684
	if (substr($settings['protocol'], 0, 3) == "TCP") {
685
			$proto = "{$proto}-{$mode}";
686
	}
687
	$dev_mode = $settings['dev_mode'];
688
	$cipher = $settings['crypto'];
689
	// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
690
	$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
691

    
692
	$interface = get_failover_interface($settings['interface']);
693
	// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
694
	$ipaddr = $settings['ipaddr'];
695

    
696
	// If a specific ip address (VIP) is requested, use it.
697
	// Otherwise, if a specific interface is requested, use it
698
	// If "any" interface was selected, local directive will be omitted.
699
	if (is_ipaddrv4($ipaddr)) {
700
		$iface_ip = $ipaddr;
701
	} else {
702
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
703
			$iface_ip=get_interface_ip($interface);
704
		}
705
	}
706
	if (is_ipaddrv6($ipaddr)) {
707
		$iface_ipv6 = $ipaddr;
708
	} else {
709
		if ((!empty($interface)) && (strcmp($interface, "any"))) {
710
			$iface_ipv6=get_interface_ipv6($interface);
711
		}
712
	}
713

    
714

    
715
	$conf = "dev {$devname}\n";
716
	if (isset($settings['verbosity_level'])) {
717
		$conf .= "verb {$settings['verbosity_level']}\n";
718
	}
719

    
720
	$conf .= "dev-type {$settings['dev_mode']}\n";
721
	switch ($settings['dev_mode']) {
722
		case "tun":
723
			if (!$settings['no_tun_ipv6']) {
724
				$conf .= "tun-ipv6\n";
725
			}
726
			break;
727
	}
728
	$conf .= "dev-node /dev/{$tunname}\n";
729
	$conf .= "writepid {$pfile}\n";
730
	$conf .= "#user nobody\n";
731
	$conf .= "#group nobody\n";
732
	$conf .= "script-security 3\n";
733
	$conf .= "daemon\n";
734
	$conf .= "keepalive 10 60\n";
735
	$conf .= "ping-timer-rem\n";
736
	$conf .= "persist-tun\n";
737
	$conf .= "persist-key\n";
738
	$conf .= "proto {$proto}\n";
739
	$conf .= "cipher {$cipher}\n";
740
	$conf .= "auth {$digest}\n";
741
	$conf .= "up /usr/local/sbin/ovpn-linkup\n";
742
	$conf .= "down /usr/local/sbin/ovpn-linkdown\n";
743
	if (file_exists("/usr/local/sbin/openvpn.attributes.sh")) {
744
		switch ($settings['mode']) {
745
			case 'server_user':
746
			case 'server_tls_user':
747
				$conf .= "client-connect /usr/local/sbin/openvpn.attributes.sh\n";
748
				$conf .= "client-disconnect /usr/local/sbin/openvpn.attributes.sh\n";
749
				break;
750
		}
751
	}
752

    
753
	/* Determine the local IP to use - and make sure it matches with the selected protocol. */
754
	if (is_ipaddrv4($iface_ip) && (stristr($settings['protocol'], "6") === false)) {
755
		$conf .= "local {$iface_ip}\n";
756
	} elseif (is_ipaddrv6($iface_ipv6) && (stristr($settings['protocol'], "6") !== false)) {
757
		$conf .= "local {$iface_ipv6}\n";
758
	}
759

    
760
	if (openvpn_validate_engine($settings['engine']) && ($settings['engine'] != "none")) {
761
		$conf .= "engine {$settings['engine']}\n";
762
	}
763

    
764
	// server specific settings
765
	if ($mode == 'server') {
766

    
767
		list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
768
		list($ipv6, $prefix) = explode('/', trim($settings['tunnel_networkv6']));
769
		$mask = gen_subnet_mask($cidr);
770

    
771
		// configure tls modes
772
		switch ($settings['mode']) {
773
			case 'p2p_tls':
774
			case 'server_tls':
775
			case 'server_user':
776
			case 'server_tls_user':
777
				$conf .= "tls-server\n";
778
				break;
779
		}
780

    
781
		// configure p2p/server modes
782
		switch ($settings['mode']) {
783
			case 'p2p_tls':
784
				// If the CIDR is less than a /30, OpenVPN will complain if you try to
785
				//  use the server directive. It works for a single client without it.
786
				//  See ticket #1417
787
				if (!empty($ip) && !empty($mask) && ($cidr < 30)) {
788
					$conf .= "server {$ip} {$mask}\n";
789
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
790
					if (is_ipaddr($ipv6)) {
791
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
792
					}
793
				}
794
			case 'p2p_shared_key':
795
				if (!empty($ip) && !empty($mask)) {
796
					list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
797
					if ($settings['dev_mode'] == 'tun') {
798
						$conf .= "ifconfig {$ip1} {$ip2}\n";
799
					} else {
800
						$conf .= "ifconfig {$ip1} {$mask}\n";
801
					}
802
				}
803
				if (!empty($ipv6) && !empty($prefix)) {
804
					list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
805
					if ($settings['dev_mode'] == 'tun') {
806
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$ipv6_2}\n";
807
					} else {
808
						$conf .= "ifconfig-ipv6 {$ipv6_1} {$prefix}\n";
809
					}
810
				}
811
				break;
812
			case 'server_tls':
813
			case 'server_user':
814
			case 'server_tls_user':
815
				if (!empty($ip) && !empty($mask)) {
816
					$conf .= "server {$ip} {$mask}\n";
817
					if (is_ipaddr($ipv6)) {
818
						$conf .= "server-ipv6 {$ipv6}/{$prefix}\n";
819
					}
820
					$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
821
				} else {
822
					if ($settings['serverbridge_dhcp']) {
823
						if ((!empty($settings['serverbridge_interface'])) && (strcmp($settings['serverbridge_interface'], "none"))) {
824
							$biface_ip=get_interface_ip($settings['serverbridge_interface']);
825
							$biface_sm=gen_subnet_mask(get_interface_subnet($settings['serverbridge_interface']));
826
							if (is_ipaddrv4($biface_ip) && is_ipaddrv4($settings['serverbridge_dhcp_start']) && is_ipaddrv4($settings['serverbridge_dhcp_end'])) {
827
								$conf .= "server-bridge {$biface_ip} {$biface_sm} {$settings['serverbridge_dhcp_start']} {$settings['serverbridge_dhcp_end']}\n";
828
								$conf .= "client-config-dir {$g['varetc_path']}/openvpn-csc/server{$vpnid}\n";
829
							} else {
830
								$conf .= "mode server\n";
831
							}
832
						} else {
833
							$conf .= "mode server\n";
834
						}
835
					}
836
				}
837
				break;
838
		}
839

    
840
		// configure user auth modes
841
		switch ($settings['mode']) {
842
			case 'server_user':
843
				$conf .= "client-cert-not-required\n";
844
			case 'server_tls_user':
845
				/* username-as-common-name is not compatible with server-bridge */
846
				if (stristr($conf, "server-bridge") === false) {
847
					$conf .= "username-as-common-name\n";
848
				}
849
				if (!empty($settings['authmode'])) {
850
					$strictusercn = "false";
851
					if ($settings['strictusercn']) {
852
						$strictusercn = "true";
853
					}
854
					$conf .= "auth-user-pass-verify \"/usr/local/sbin/ovpn_auth_verify user '{$settings['authmode']}' {$strictusercn} {$mode_id}\" via-env\n";
855
				}
856
				break;
857
		}
858
		if (!isset($settings['cert_depth']) && (strstr($settings['mode'], 'tls'))) {
859
			$settings['cert_depth'] = 1;
860
		}
861
		if (is_numeric($settings['cert_depth'])) {
862
			if (($mode == 'client') && empty($settings['certref'])) {
863
				$cert = "";
864
			} else {
865
				$cert = lookup_cert($settings['certref']);
866
				/* XXX: Seems not used at all! */
867
				$servercn = urlencode(cert_get_cn($cert['crt']));
868
				$conf .= "tls-verify \"/usr/local/sbin/ovpn_auth_verify tls '{$servercn}' {$settings['cert_depth']}\"\n";
869
			}
870
		}
871

    
872
		// The local port to listen on
873
		$conf .= "lport {$settings['local_port']}\n";
874

    
875
		// The management port to listen on
876
		// Use unix socket to overcome the problem on any type of server
877
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
878
		//$conf .= "management 127.0.0.1 {$settings['local_port']}\n";
879

    
880
		if ($settings['maxclients']) {
881
			$conf .= "max-clients {$settings['maxclients']}\n";
882
		}
883

    
884
		// Can we push routes
885
		if ($settings['local_network']) {
886
			$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
887
		}
888
		if ($settings['local_networkv6']) {
889
			$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
890
		}
891

    
892
		switch ($settings['mode']) {
893
			case 'server_tls':
894
			case 'server_user':
895
			case 'server_tls_user':
896
				// Configure client dhcp options
897
				openvpn_add_dhcpopts($settings, $conf);
898
				if ($settings['client2client']) {
899
					$conf .= "client-to-client\n";
900
				}
901
				break;
902
		}
903
		if (isset($settings['duplicate_cn'])) {
904
			$conf .= "duplicate-cn\n";
905
		}
906
	}
907

    
908
	// client specific settings
909

    
910
	if ($mode == 'client') {
911

    
912
		// configure p2p mode
913
		switch ($settings['mode']) {
914
			case 'p2p_tls':
915
				$conf .= "tls-client\n";
916
			case 'shared_key':
917
				$conf .= "client\n";
918
				break;
919
		}
920

    
921
		// If there is no bind option at all (ip and/or port), add "nobind" directive
922
		//  Otherwise, use the local port if defined, failing that, use lport 0 to
923
		//  ensure a random source port.
924
		if ((empty($iface_ip)) && (!$settings['local_port'])) {
925
			$conf .= "nobind\n";
926
		} elseif ($settings['local_port']) {
927
			$conf .= "lport {$settings['local_port']}\n";
928
		} else {
929
			$conf .= "lport 0\n";
930
		}
931

    
932
		// Use unix socket to overcome the problem on any type of server
933
		$conf .= "management {$g['varetc_path']}/openvpn/{$mode_id}.sock unix\n";
934

    
935
		// The remote server
936
		$conf .= "remote {$settings['server_addr']} {$settings['server_port']}\n";
937

    
938
		if (!empty($settings['use_shaper'])) {
939
			$conf .= "shaper {$settings['use_shaper']}\n";
940
		}
941

    
942
		if (!empty($settings['tunnel_network'])) {
943
			list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
944
			$mask = gen_subnet_mask($cidr);
945
			list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
946
			if ($settings['dev_mode'] == 'tun') {
947
				$conf .= "ifconfig {$ip2} {$ip1}\n";
948
			} else {
949
				$conf .= "ifconfig {$ip2} {$mask}\n";
950
			}
951
		}
952

    
953
		if (!empty($settings['tunnel_networkv6'])) {
954
			list($ipv6, $prefix) = explode('/', trim($settings['tunnel_networkv6']));
955
			list($ipv6_1, $ipv6_2) = openvpn_get_interface_ipv6($ipv6, $prefix);
956
			if ($settings['dev_mode'] == 'tun') {
957
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$ipv6_1}\n";
958
			} else {
959
				$conf .= "ifconfig-ipv6 {$ipv6_2} {$prefix}\n";
960
			}
961
		}
962

    
963
		if (($settings['auth_user'] || $settings['auth_pass']) && $settings['mode'] == "p2p_tls") {
964
			$up_file = "{$g['varetc_path']}/openvpn/{$mode_id}.up";
965
			$conf .= "auth-user-pass {$up_file}\n";
966
			if ($settings['auth_user']) {
967
				$userpass = "{$settings['auth_user']}\n";
968
			} else {
969
				$userpass = "";
970
			}
971
			if ($settings['auth_pass']) {
972
				$userpass .= "{$settings['auth_pass']}\n";
973
			}
974
			// If only auth_pass is given, then it acts like a user name and we put a blank line where pass would normally go.
975
			if (!($settings['auth_user'] && $settings['auth_pass'])) {
976
				$userpass .= "\n";
977
			}
978
			file_put_contents($up_file, $userpass);
979
		}
980

    
981
		if ($settings['proxy_addr']) {
982
			$conf .= "http-proxy {$settings['proxy_addr']} {$settings['proxy_port']}";
983
			if ($settings['proxy_authtype'] != "none") {
984
				$conf .= " {$g['varetc_path']}/openvpn/{$mode_id}.pas {$settings['proxy_authtype']}";
985
				$proxypas = "{$settings['proxy_user']}\n";
986
				$proxypas .= "{$settings['proxy_passwd']}\n";
987
				file_put_contents("{$g['varetc_path']}/openvpn/{$mode_id}.pas", $proxypas);
988
			}
989
			$conf .= " \n";
990
		}
991
	}
992

    
993
	// Add a remote network route if set, and only for p2p modes.
994
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE)) {
995
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false);
996
	}
997
	// Add a remote network route if set, and only for p2p modes.
998
	if ((substr($settings['mode'], 0, 3) == "p2p") && (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE)) {
999
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false);
1000
	}
1001

    
1002
	// Write the settings for the keys
1003
	switch ($settings['mode']) {
1004
		case 'p2p_shared_key':
1005
			openvpn_add_keyfile($settings['shared_key'], $conf, $mode_id, "secret");
1006
			break;
1007
		case 'p2p_tls':
1008
		case 'server_tls':
1009
		case 'server_tls_user':
1010
		case 'server_user':
1011
			$ca = lookup_ca($settings['caref']);
1012
			openvpn_add_keyfile($ca['crt'], $conf, $mode_id, "ca");
1013

    
1014
			if (!empty($settings['certref'])) {
1015
				$cert = lookup_cert($settings['certref']);
1016
				openvpn_add_keyfile($cert['crt'], $conf, $mode_id, "cert");
1017
				openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key");
1018
			}
1019
			if ($mode == 'server') {
1020
				$conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n";
1021
			}
1022
			if (!empty($settings['crlref'])) {
1023
				$crl = lookup_crl($settings['crlref']);
1024
				crl_update($crl);
1025
				openvpn_add_keyfile($crl['text'], $conf, $mode_id, "crl-verify");
1026
			}
1027
			if ($settings['tls']) {
1028
				if ($mode == "server") {
1029
					$tlsopt = 0;
1030
				} else {
1031
					$tlsopt = 1;
1032
				}
1033
				openvpn_add_keyfile($settings['tls'], $conf, $mode_id, "tls-auth", $tlsopt);
1034
			}
1035
			break;
1036
	}
1037

    
1038
	if (!empty($settings['compression'])) {
1039
		$conf .= "comp-lzo {$settings['compression']}\n";
1040
	}
1041

    
1042
	if ($settings['passtos']) {
1043
		$conf .= "passtos\n";
1044
	}
1045

    
1046
	if ($settings['resolve_retry']) {
1047
		$conf .= "resolv-retry infinite\n";
1048
	} else if ($mode == 'client') {
1049
		$conf .= "resolv-retry infinite\n";
1050
	}
1051

    
1052
	if ($settings['dynamic_ip']) {
1053
		$conf .= "persist-remote-ip\n";
1054
		$conf .= "float\n";
1055
	}
1056

    
1057
	// If the server is not a TLS server or it has a tunnel network CIDR less than a /30, skip this.
1058
	if (in_array($settings['mode'], $openvpn_tls_server_modes) && (!empty($ip) && !empty($mask) && ($cidr < 30)) && $settings['dev_mode'] != "tap") {
1059
		if (empty($settings['topology'])) {
1060
			$settings['topology'] = "subnet";
1061
		}
1062
		$conf .= "topology {$settings['topology']}\n";
1063
	}
1064

    
1065
	// New client features
1066
	if ($mode == "client") {
1067
		// Dont pull routes checkbox
1068
		if ($settings['route_no_pull']) {
1069
			$conf .= "route-nopull\n";
1070
		}
1071

    
1072
		// Dont add/remove routes checkbox
1073
		if ($settings['route_no_exec']) {
1074
			$conf .= "route-noexec\n";
1075
		}
1076
	}
1077

    
1078
	openvpn_add_custom($settings, $conf);
1079

    
1080
	openvpn_create_dirs();
1081
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.conf";
1082
	file_put_contents($fpath, $conf);
1083
	unset($conf);
1084
	$fpath = "{$g['varetc_path']}/openvpn/{$mode_id}.interface";
1085
	file_put_contents($fpath, $interface);
1086
	//chown($fpath, 'nobody');
1087
	//chgrp($fpath, 'nobody');
1088
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1089
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.interface", 0600);
1090
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.key", 0600);
1091
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.tls-auth", 0600);
1092
	@chmod("{$g['varetc_path']}/openvpn/{$mode_id}.conf", 0600);
1093
}
1094

    
1095
function openvpn_restart($mode, $settings) {
1096
	global $g, $config;
1097

    
1098
	$vpnid = $settings['vpnid'];
1099
	$mode_id = $mode.$vpnid;
1100

    
1101
	/* kill the process if running */
1102
	$pfile = $g['varrun_path']."/openvpn_{$mode_id}.pid";
1103
	if (file_exists($pfile)) {
1104

    
1105
		/* read the pid file */
1106
		$pid = rtrim(file_get_contents($pfile));
1107
		unlink($pfile);
1108

    
1109
		/* send a term signal to the process */
1110
		posix_kill($pid, SIGTERM);
1111

    
1112
		/* wait until the process exits, or timeout and kill it */
1113
		$i = 0;
1114
		while (posix_kill($pid, 0)) {
1115
			usleep(250000);
1116
			if ($i > 10) {
1117
				log_error(sprintf(gettext('OpenVPN ID %1$s PID %2$s still running, killing.'), $mode_id, $pid));
1118
				posix_kill($pid, SIGKILL);
1119
				usleep(500000);
1120
			}
1121
			$i++;
1122
		}
1123
	}
1124

    
1125
	if (isset($settings['disable'])) {
1126
		return;
1127
	}
1128

    
1129
	/* Do not start a client if we are a CARP backup on this vip! */
1130
	if (($mode == "client") && (strstr($settings['interface'], "_vip") && get_carp_interface_status($settings['interface']) != "MASTER")) {
1131
		return;
1132
	}
1133

    
1134
	/* Check if client is bound to a gateway group */
1135
	$a_groups = return_gateway_groups_array();
1136
	if (is_array($a_groups[$settings['interface']])) {
1137
		/* the interface is a gateway group. If a vip is defined and its a CARP backup then do not start */
1138
		if (($a_groups[$settings['interface']][0]['vip'] <> "") && (get_carp_interface_status($a_groups[$settings['interface']][0]['vip']) != "MASTER")) {
1139
			return;
1140
		}
1141
	}
1142

    
1143
	/* start the new process */
1144
	$fpath = $g['varetc_path']."/openvpn/{$mode_id}.conf";
1145
	openvpn_clear_route($mode, $settings);
1146
	mwexec_bg("/usr/local/sbin/openvpn --config " . escapeshellarg($fpath));
1147

    
1148
	if (!platform_booting()) {
1149
		send_event("filter reload");
1150
	}
1151
}
1152

    
1153
function openvpn_delete($mode, & $settings) {
1154
	global $g, $config;
1155

    
1156
	$vpnid = $settings['vpnid'];
1157
	$mode_id = $mode.$vpnid;
1158

    
1159
	if (isset($settings['dev_mode'])) {
1160
		$tunname = "{$settings['dev_mode']}{$vpnid}";
1161
	} else {
1162
		/* defaults to tun */
1163
		$tunname = "tun{$vpnid}";
1164
	}
1165

    
1166
	if ($mode == "server") {
1167
		$devname = "ovpns{$vpnid}";
1168
	} else {
1169
		$devname = "ovpnc{$vpnid}";
1170
	}
1171

    
1172
	/* kill the process if running */
1173
	$pfile = "{$g['varrun_path']}/openvpn_{$mode_id}.pid";
1174
	if (file_exists($pfile)) {
1175

    
1176
		/* read the pid file */
1177
		$pid = trim(file_get_contents($pfile));
1178
		unlink($pfile);
1179

    
1180
		/* send a term signal to the process */
1181
		posix_kill($pid, SIGTERM);
1182
	}
1183

    
1184
	/* remove the device from the openvpn group */
1185
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " -group openvpn");
1186

    
1187
	/* restore the original adapter name */
1188
	mwexec("/sbin/ifconfig " . escapeshellarg($devname) . " name " . escapeshellarg($tunname));
1189

    
1190
	/* remove the configuration files */
1191
	@array_map('unlink', glob("{$g['varetc_path']}/openvpn/{$mode_id}.*"));
1192
}
1193

    
1194
function openvpn_resync_csc(& $settings) {
1195
	global $g, $config, $openvpn_tls_server_modes;
1196

    
1197
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1198

    
1199
	if (isset($settings['disable'])) {
1200
		openvpn_delete_csc($settings);
1201
		return;
1202
	}
1203
	openvpn_create_dirs();
1204

    
1205
	if (empty($settings['server_list'])) {
1206
		$csc_server_list = array();
1207
	} else {
1208
		$csc_server_list = explode(",", $settings['server_list']);
1209
	}
1210

    
1211
	$conf = '';
1212
	if ($settings['block']) {
1213
		$conf .= "disable\n";
1214
	}
1215

    
1216
	if ($settings['push_reset']) {
1217
		$conf .= "push-reset\n";
1218
	}
1219

    
1220
	if ($settings['local_network']) {
1221
		$conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true);
1222
	}
1223
	if ($settings['local_networkv6']) {
1224
		$conf .= openvpn_gen_routes($settings['local_networkv6'], "ipv6", true);
1225
	}
1226

    
1227
	// Add a remote network iroute if set
1228
	if (openvpn_validate_cidr($settings['remote_network'], "", true, "ipv4") === FALSE) {
1229
		$conf .= openvpn_gen_routes($settings['remote_network'], "ipv4", false, true);
1230
	}
1231
	// Add a remote network iroute if set
1232
	if (openvpn_validate_cidr($settings['remote_networkv6'], "", true, "ipv6") === FALSE) {
1233
		$conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true);
1234
	}
1235

    
1236
	openvpn_add_dhcpopts($settings, $conf);
1237

    
1238
	if ($settings['gwredir']) {
1239
		$conf .= "push \"redirect-gateway def1\"\n";
1240
	}
1241

    
1242
	openvpn_add_custom($settings, $conf);
1243
	/* Loop through servers, find which ones can use this CSC */
1244
	if (is_array($config['openvpn']['openvpn-server'])) {
1245
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1246
			if (isset($serversettings['disable'])) {
1247
				continue;
1248
			}
1249
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1250
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1251
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1252
					$csc_conf = $conf;
1253

    
1254
					if (!empty($serversettings['tunnel_network']) && !empty($settings['tunnel_network'])) {
1255
						list($ip, $mask) = explode('/', trim($settings['tunnel_network']));
1256
						if (($serversettings['dev_mode'] == 'tap') || ($serversettings['topology'] == "subnet")) {
1257
							$csc_conf .= "ifconfig-push {$ip} " . gen_subnet_mask($mask) . "\n";
1258
						} else {
1259
							/* Because this is being pushed, the order from the client's point of view. */
1260
							$baselong = gen_subnetv4($ip, $mask);
1261
							$serverip = ip_after($baselong, 1);
1262
							$clientip = ip_after($baselong, 2);
1263
							$csc_conf .= "ifconfig-push {$clientip} {$serverip}\n";
1264
						}
1265
					}
1266
					file_put_contents($csc_path, $csc_conf);
1267
					chown($csc_path, 'nobody');
1268
					chgrp($csc_path, 'nobody');
1269
				}
1270
			}
1271
		}
1272
	}
1273
}
1274

    
1275
function openvpn_delete_csc(& $settings) {
1276
	global $g, $config, $openvpn_tls_server_modes;
1277
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1278
	if (empty($settings['server_list'])) {
1279
		$csc_server_list = array();
1280
	} else {
1281
		$csc_server_list = explode(",", $settings['server_list']);
1282
	}
1283

    
1284
	/* Loop through servers, find which ones used this CSC */
1285
	if (is_array($config['openvpn']['openvpn-server'])) {
1286
		foreach ($config['openvpn']['openvpn-server'] as $serversettings) {
1287
			if (isset($serversettings['disable'])) {
1288
				continue;
1289
			}
1290
			if (in_array($serversettings['mode'], $openvpn_tls_server_modes)) {
1291
				if ($serversettings['vpnid'] && (empty($csc_server_list) || in_array($serversettings['vpnid'], $csc_server_list))) {
1292
					$csc_path = "{$csc_base_path}/server{$serversettings['vpnid']}/" . basename($settings['common_name']);
1293
					unlink_if_exists($csc_path);
1294
				}
1295
			}
1296
		}
1297
	}
1298
}
1299

    
1300
// Resync the configuration and restart the VPN
1301
function openvpn_resync($mode, $settings) {
1302
	openvpn_reconfigure($mode, $settings);
1303
	openvpn_restart($mode, $settings);
1304
}
1305

    
1306
// Resync and restart all VPNs
1307
function openvpn_resync_all($interface = "") {
1308
	global $g, $config;
1309

    
1310
	openvpn_create_dirs();
1311

    
1312
	if (!is_array($config['openvpn'])) {
1313
		$config['openvpn'] = array();
1314
	}
1315

    
1316
/*
1317
	if (!$config['openvpn']['dh-parameters']) {
1318
		echo "Configuring OpenVPN Parameters ...\n";
1319
		$dh_parameters = openvpn_create_dhparams(1024);
1320
		$dh_parameters = base64_encode($dh_parameters);
1321
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1322
		write_config("OpenVPN DH parameters");
1323
	}
1324

    
1325
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1326
	if (!file_exists($path_ovdh)) {
1327
		$dh_parameters = $config['openvpn']['dh-parameters'];
1328
		$dh_parameters = base64_decode($dh_parameters);
1329
		file_put_contents($path_ovdh, $dh_parameters);
1330
	}
1331
*/
1332
	if ($interface <> "") {
1333
		log_error(sprintf(gettext("Resyncing OpenVPN instances for interface %s."), convert_friendly_interface_to_friendly_descr($interface)));
1334
	} else {
1335
		log_error(gettext("Resyncing OpenVPN instances."));
1336
	}
1337

    
1338
	if (is_array($config['openvpn']['openvpn-server'])) {
1339
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1340
			if ($interface <> "" && $interface != $settings['interface']) {
1341
				continue;
1342
			}
1343
			openvpn_resync('server', $settings);
1344
		}
1345
	}
1346

    
1347
	if (is_array($config['openvpn']['openvpn-client'])) {
1348
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1349
			if ($interface <> "" && $interface != $settings['interface']) {
1350
				continue;
1351
			}
1352
			openvpn_resync('client', $settings);
1353
		}
1354
	}
1355

    
1356
	if (is_array($config['openvpn']['openvpn-csc'])) {
1357
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1358
			openvpn_resync_csc($settings);
1359
		}
1360
	}
1361

    
1362
}
1363

    
1364
// Resync and restart all VPNs using a gateway group.
1365
function openvpn_resync_gwgroup($gwgroupname = "") {
1366
	global $g, $config;
1367

    
1368
	if ($gwgroupname <> "") {
1369
		if (is_array($config['openvpn']['openvpn-server'])) {
1370
			foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1371
				if ($gwgroupname == $settings['interface']) {
1372
					log_error(sprintf(gettext('Resyncing OpenVPN for gateway group %1$s server %2$s.'), $gwgroupname, $settings["description"]));
1373
					openvpn_resync('server', $settings);
1374
				}
1375
			}
1376
		}
1377

    
1378
		if (is_array($config['openvpn']['openvpn-client'])) {
1379
			foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1380
				if ($gwgroupname == $settings['interface']) {
1381
					log_error(sprintf(gettext('Resyncing OpenVPN for gateway group %1$s client %2$s.'), $gwgroupname, $settings["description"]));
1382
					openvpn_resync('client', $settings);
1383
				}
1384
			}
1385
		}
1386

    
1387
		// Note: no need to resysnc Client Specific (csc) here, as changes to the OpenVPN real interface do not effect these.
1388

    
1389
	} else {
1390
		log_error(gettext("openvpn_resync_gwgroup called with null gwgroup parameter."));
1391
	}
1392
}
1393

    
1394
function openvpn_get_active_servers($type="multipoint") {
1395
	global $config, $g;
1396

    
1397
	$servers = array();
1398
	if (is_array($config['openvpn']['openvpn-server'])) {
1399
		foreach ($config['openvpn']['openvpn-server'] as & $settings) {
1400
			if (empty($settings) || isset($settings['disable'])) {
1401
				continue;
1402
			}
1403

    
1404
			$prot = $settings['protocol'];
1405
			$port = $settings['local_port'];
1406

    
1407
			$server = array();
1408
			$server['port'] = ($settings['local_port']) ? $settings['local_port'] : 1194;
1409
			$server['mode'] = $settings['mode'];
1410
			if ($settings['description']) {
1411
				$server['name'] = "{$settings['description']} {$prot}:{$port}";
1412
			} else {
1413
				$server['name'] = "Server {$prot}:{$port}";
1414
			}
1415
			$server['conns'] = array();
1416
			$server['vpnid'] = $settings['vpnid'];
1417
			$server['mgmt'] = "server{$server['vpnid']}";
1418
			$socket = "unix://{$g['varetc_path']}/openvpn/{$server['mgmt']}.sock";
1419
			list($tn, $sm) = explode('/', trim($settings['tunnel_network']));
1420

    
1421
			if ((($server['mode'] == "p2p_shared_key") || ($sm >= 30)) && ($type == "p2p")) {
1422
				$servers[] = openvpn_get_client_status($server, $socket);
1423
			} elseif (($server['mode'] != "p2p_shared_key") && ($type == "multipoint") && ($sm < 30)) {
1424
				$servers[] = openvpn_get_server_status($server, $socket);
1425
			}
1426
		}
1427
	}
1428
	return $servers;
1429
}
1430

    
1431
function openvpn_get_server_status($server, $socket) {
1432
	$errval = null;
1433
	$errstr = null;
1434
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1435
	if ($fp) {
1436
		stream_set_timeout($fp, 1);
1437

    
1438
		/* send our status request */
1439
		fputs($fp, "status 2\n");
1440

    
1441
		/* recv all response lines */
1442
		while (!feof($fp)) {
1443

    
1444
			/* read the next line */
1445
			$line = fgets($fp, 1024);
1446

    
1447
			$info = stream_get_meta_data($fp);
1448
			if ($info['timed_out']) {
1449
				break;
1450
			}
1451

    
1452
			/* parse header list line */
1453
			if (strstr($line, "HEADER")) {
1454
				continue;
1455
			}
1456

    
1457
			/* parse end of output line */
1458
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1459
				break;
1460
			}
1461

    
1462
			/* parse client list line */
1463
			if (strstr($line, "CLIENT_LIST")) {
1464
				$list = explode(",", $line);
1465
				$conn = array();
1466
				$conn['common_name'] = $list[1];
1467
				$conn['remote_host'] = $list[2];
1468
				$conn['virtual_addr'] = $list[3];
1469
				$conn['bytes_recv'] = $list[4];
1470
				$conn['bytes_sent'] = $list[5];
1471
				$conn['connect_time'] = $list[6];
1472
				$server['conns'][] = $conn;
1473
			}
1474
			/* parse routing table lines */
1475
			if (strstr($line, "ROUTING_TABLE")) {
1476
				$list = explode(",", $line);
1477
				$conn = array();
1478
				$conn['virtual_addr'] = $list[1];
1479
				$conn['common_name'] = $list[2];
1480
				$conn['remote_host'] = $list[3];
1481
				$conn['last_time'] = $list[4];
1482
				$server['routes'][] = $conn;
1483
			}
1484
		}
1485

    
1486
		/* cleanup */
1487
		fclose($fp);
1488
	} else {
1489
		$conn = array();
1490
		$conn['common_name'] = "[error]";
1491
		$conn['remote_host'] = gettext("Unable to contact daemon");
1492
		$conn['virtual_addr'] = gettext("Service not running?");
1493
		$conn['bytes_recv'] = 0;
1494
		$conn['bytes_sent'] = 0;
1495
		$conn['connect_time'] = 0;
1496
		$server['conns'][] = $conn;
1497
	}
1498
	return $server;
1499
}
1500

    
1501
function openvpn_get_active_clients() {
1502
	global $config, $g;
1503

    
1504
	$clients = array();
1505
	if (is_array($config['openvpn']['openvpn-client'])) {
1506
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1507

    
1508
			if (empty($settings) || isset($settings['disable'])) {
1509
				continue;
1510
			}
1511

    
1512
			$prot = $settings['protocol'];
1513
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1514

    
1515
			$client = array();
1516
			$client['port'] = $settings['local_port'];
1517
			if ($settings['description']) {
1518
				$client['name'] = "{$settings['description']} {$prot}{$port}";
1519
			} else {
1520
				$client['name'] = "Client {$prot}{$port}";
1521
			}
1522

    
1523
			$client['vpnid'] = $settings['vpnid'];
1524
			$client['mgmt'] = "client{$client['vpnid']}";
1525
			$socket = "unix://{$g['varetc_path']}/openvpn/{$client['mgmt']}.sock";
1526
			$client['status']="down";
1527

    
1528
			$clients[] = openvpn_get_client_status($client, $socket);
1529
		}
1530
	}
1531
	return $clients;
1532
}
1533

    
1534
function openvpn_get_client_status($client, $socket) {
1535
	$errval = null;
1536
	$errstr = null;
1537
	$fp = @stream_socket_client($socket, $errval, $errstr, 1);
1538
	if ($fp) {
1539
		stream_set_timeout($fp, 1);
1540
		/* send our status request */
1541
		fputs($fp, "state 1\n");
1542

    
1543
		/* recv all response lines */
1544
		while (!feof($fp)) {
1545
			/* read the next line */
1546
			$line = fgets($fp, 1024);
1547

    
1548
			$info = stream_get_meta_data($fp);
1549
			if ($info['timed_out']) {
1550
				break;
1551
			}
1552

    
1553
			/* Get the client state */
1554
			if (strstr($line, "CONNECTED")) {
1555
				$client['status'] = "up";
1556
				$list = explode(",", $line);
1557

    
1558
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1559
				$client['virtual_addr'] = $list[3];
1560
				$client['remote_host'] = $list[4];
1561
			}
1562
			if (strstr($line, "CONNECTING")) {
1563
				$client['status'] = "connecting";
1564
			}
1565
			if (strstr($line, "ASSIGN_IP")) {
1566
				$client['status'] = "waiting";
1567
				$list = explode(",", $line);
1568

    
1569
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1570
				$client['virtual_addr'] = $list[3];
1571
			}
1572
			if (strstr($line, "RECONNECTING")) {
1573
				$client['status'] = "reconnecting";
1574
				$list = explode(",", $line);
1575

    
1576
				$client['connect_time'] = date("D M j G:i:s Y", $list[0]);
1577
				$client['status'] .= "; " . $list[2];
1578
			}
1579
			/* parse end of output line */
1580
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1581
				break;
1582
			}
1583
		}
1584

    
1585
		/* If up, get read/write stats */
1586
		if (strcmp($client['status'], "up") == 0) {
1587
			fputs($fp, "status 2\n");
1588
			/* recv all response lines */
1589
			while (!feof($fp)) {
1590
				/* read the next line */
1591
				$line = fgets($fp, 1024);
1592

    
1593
				$info = stream_get_meta_data($fp);
1594
				if ($info['timed_out']) {
1595
					break;
1596
				}
1597

    
1598
				if (strstr($line, "TCP/UDP read bytes")) {
1599
					$list = explode(",", $line);
1600
					$client['bytes_recv'] = $list[1];
1601
				}
1602

    
1603
				if (strstr($line, "TCP/UDP write bytes")) {
1604
					$list = explode(",", $line);
1605
					$client['bytes_sent'] = $list[1];
1606
				}
1607

    
1608
				/* parse end of output line */
1609
				if (strstr($line, "END")) {
1610
					break;
1611
				}
1612
			}
1613
		}
1614

    
1615
		fclose($fp);
1616

    
1617
	} else {
1618
		$client['remote_host'] = gettext("Unable to contact daemon");
1619
		$client['virtual_addr'] = gettext("Service not running?");
1620
		$client['bytes_recv'] = 0;
1621
		$client['bytes_sent'] = 0;
1622
		$client['connect_time'] = 0;
1623
	}
1624
	return $client;
1625
}
1626

    
1627
function openvpn_kill_client($port, $remipp) {
1628
	global $g;
1629

    
1630
	//$tcpsrv = "tcp://127.0.0.1:{$port}";
1631
	$tcpsrv = "unix://{$g['varetc_path']}/openvpn/{$port}.sock";
1632
	$errval = null;
1633
	$errstr = null;
1634

    
1635
	/* open a tcp connection to the management port of each server */
1636
	$fp = @stream_socket_client($tcpsrv, $errval, $errstr, 1);
1637
	$killed = -1;
1638
	if ($fp) {
1639
		stream_set_timeout($fp, 1);
1640
		fputs($fp, "kill {$remipp}\n");
1641
		while (!feof($fp)) {
1642
			$line = fgets($fp, 1024);
1643

    
1644
			$info = stream_get_meta_data($fp);
1645
			if ($info['timed_out']) {
1646
				break;
1647
			}
1648

    
1649
			/* parse header list line */
1650
			if (strpos($line, "INFO:") !== false) {
1651
				continue;
1652
			}
1653
			if (strpos($line, "SUCCESS") !== false) {
1654
				$killed = 0;
1655
			}
1656
			break;
1657
		}
1658
		fclose($fp);
1659
	}
1660
	return $killed;
1661
}
1662

    
1663
function openvpn_refresh_crls() {
1664
	global $g, $config;
1665

    
1666
	openvpn_create_dirs();
1667

    
1668
	if (is_array($config['openvpn']['openvpn-server'])) {
1669
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1670
			if (empty($settings)) {
1671
				continue;
1672
			}
1673
			if (isset($settings['disable'])) {
1674
				continue;
1675
			}
1676
			// Write the settings for the keys
1677
			switch ($settings['mode']) {
1678
				case 'p2p_tls':
1679
				case 'server_tls':
1680
				case 'server_tls_user':
1681
				case 'server_user':
1682
					if (!empty($settings['crlref'])) {
1683
						$crl = lookup_crl($settings['crlref']);
1684
						crl_update($crl);
1685
						$fpath = $g['varetc_path']."/openvpn/server{$settings['vpnid']}.crl-verify";
1686
						file_put_contents($fpath, base64_decode($crl['text']));
1687
						@chmod($fpath, 0644);
1688
					}
1689
					break;
1690
			}
1691
		}
1692
	}
1693
}
1694

    
1695
function openvpn_create_dirs() {
1696
	global $g, $config, $openvpn_tls_server_modes;
1697
	if (!is_dir("{$g['varetc_path']}/openvpn")) {
1698
		safe_mkdir("{$g['varetc_path']}/openvpn", 0750);
1699
	}
1700
	if (!is_dir("{$g['varetc_path']}/openvpn-csc")) {
1701
		safe_mkdir("{$g['varetc_path']}/openvpn-csc", 0750);
1702
	}
1703

    
1704
	/* Check for enabled servers and create server-specific CSC dirs */
1705
	if (is_array($config['openvpn']['openvpn-server'])) {
1706
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1707
			if (isset($settings['disable'])) {
1708
				continue;
1709
			}
1710
			if (in_array($settings['mode'], $openvpn_tls_server_modes)) {
1711
				if ($settings['vpnid']) {
1712
					safe_mkdir("{$g['varetc_path']}/openvpn-csc/server{$settings['vpnid']}");
1713
				}
1714
			}
1715
		}
1716
	}
1717
}
1718

    
1719
function openvpn_get_interface_ip($ip, $cidr) {
1720
	$subnet = gen_subnetv4($ip, $cidr);
1721
	$ip1 = ip_after($subnet);
1722
	$ip2 = ip_after($ip1);
1723
	return array($ip1, $ip2);
1724
}
1725

    
1726
function openvpn_get_interface_ipv6($ipv6, $prefix) {
1727
	$basev6 = gen_subnetv6($ipv6, $prefix);
1728
	// Is there a better way to do this math?
1729
	$ipv6_arr = explode(':', $basev6);
1730
	$last = hexdec(array_pop($ipv6_arr));
1731
	$ipv6_1 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 1)));
1732
	$ipv6_2 = Net_IPv6::compress(Net_IPv6::uncompress(implode(':', $ipv6_arr) . ':' . dechex($last + 2)));
1733
	return array($ipv6_1, $ipv6_2);
1734
}
1735

    
1736
function openvpn_clear_route($mode, $settings) {
1737
	if (empty($settings['tunnel_network'])) {
1738
		return;
1739
	}
1740
	list($ip, $cidr) = explode('/', trim($settings['tunnel_network']));
1741
	$mask = gen_subnet_mask($cidr);
1742
	$clear_route = false;
1743

    
1744
	switch ($settings['mode']) {
1745
		case 'shared_key':
1746
			$clear_route = true;
1747
			break;
1748
		case 'p2p_tls':
1749
		case 'p2p_shared_key':
1750
			if ($cidr == 30) {
1751
				$clear_route = true;
1752
			}
1753
			break;
1754
	}
1755

    
1756
	if ($clear_route && !empty($ip) && !empty($mask)) {
1757
		list($ip1, $ip2) = openvpn_get_interface_ip($ip, $cidr);
1758
		$ip_to_clear = ($mode == "server") ? $ip1 : $ip2;
1759
		/* XXX: Family for route? */
1760
		mwexec("/sbin/route -q delete {$ip_to_clear}");
1761
	}
1762
}
1763

    
1764
function openvpn_gen_routes($value, $ipproto = "ipv4", $push = false, $iroute = false) {
1765
	$routes = "";
1766
	if (empty($value)) {
1767
		return "";
1768
	}
1769
	$networks = explode(',', $value);
1770

    
1771
	foreach ($networks as $network) {
1772
		if ($ipproto == "ipv4") {
1773
			$route = openvpn_gen_route_ipv4($network, $iroute);
1774
		} else {
1775
			$route = openvpn_gen_route_ipv6($network, $iroute);
1776
		}
1777

    
1778
		if ($push) {
1779
			$routes .= "push \"{$route}\"\n";
1780
		} else {
1781
			$routes .= "{$route}\n";
1782
		}
1783
	}
1784
	return $routes;
1785
}
1786

    
1787
function openvpn_gen_route_ipv4($network, $iroute = false) {
1788
	$i = ($iroute) ? "i" : "";
1789
	list($ip, $mask) = explode('/', trim($network));
1790
	$mask = gen_subnet_mask($mask);
1791
	return "{$i}route $ip $mask";
1792
}
1793

    
1794
function openvpn_gen_route_ipv6($network, $iroute = false) {
1795
	$i = ($iroute) ? "i" : "";
1796
	list($ipv6, $prefix) = explode('/', trim($network));
1797
	if (empty($prefix)) {
1798
		$prefix = "128";
1799
	}
1800
	return "{$i}route-ipv6 ${ipv6}/${prefix}";
1801
}
1802

    
1803
function openvpn_get_settings($mode, $vpnid) {
1804
	global $config;
1805

    
1806
	if (is_array($config['openvpn']['openvpn-server'])) {
1807
		foreach ($config['openvpn']['openvpn-server'] as $settings) {
1808
			if (isset($settings['disable'])) {
1809
				continue;
1810
			}
1811

    
1812
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1813
				return $settings;
1814
			}
1815
		}
1816
	}
1817

    
1818
	if (is_array($config['openvpn']['openvpn-client'])) {
1819
		foreach ($config['openvpn']['openvpn-client'] as $settings) {
1820
			if (isset($settings['disable'])) {
1821
				continue;
1822
			}
1823

    
1824
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1825
				return $settings;
1826
			}
1827
		}
1828
	}
1829

    
1830
	return array();
1831
}
1832

    
1833
function openvpn_restart_by_vpnid($mode, $vpnid) {
1834
	$settings = openvpn_get_settings($mode, $vpnid);
1835
	openvpn_restart($mode, $settings);
1836
}
1837

    
1838
?>
(37-37/65)