Project

General

Profile

Download (52.1 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
 * Copyright (c) 2004 Peter Curran (peter@closeconsultants.com).
15
 * All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or without
18
 * modification, are permitted provided that the following conditions are met:
19
 *
20
 * 1. Redistributions of source code must retain the above copyright notice,
21
 *    this list of conditions and the following disclaimer.
22
 *
23
 * 2. Redistributions in binary form must reproduce the above copyright
24
 *    notice, this list of conditions and the following disclaimer in
25
 *    the documentation and/or other materials provided with the
26
 *    distribution.
27
 *
28
 * 3. All advertising materials mentioning features or use of this software
29
 *    must display the following acknowledgment:
30
 *    "This product includes software developed by the pfSense Project
31
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
32
 *
33
 * 4. The names "pfSense" and "pfSense Project" must not be used to
34
 *    endorse or promote products derived from this software without
35
 *    prior written permission. For written permission, please contact
36
 *    coreteam@pfsense.org.
37
 *
38
 * 5. Products derived from this software may not be called "pfSense"
39
 *    nor may "pfSense" appear in their names without prior written
40
 *    permission of the Electric Sheep Fencing, LLC.
41
 *
42
 * 6. Redistributions of any form whatsoever must retain the following
43
 *    acknowledgment:
44
 *
45
 * "This product includes software developed by the pfSense Project
46
 * for use in the pfSense software distribution (http://www.pfsense.org/).
47
 *
48
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
49
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
52
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59
 * OF THE POSSIBILITY OF SUCH DAMAGE.
60
 */
61

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

    
67
global $openvpn_prots;
68
$openvpn_prots = array("UDP", "UDP6", "TCP", "TCP6");
69

    
70
global $openvpn_dev_mode;
71
$openvpn_dev_mode = array("tun", "tap");
72

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

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

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

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

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

    
124
global $openvpn_tls_server_modes;
125
$openvpn_tls_server_modes = array('p2p_tls', 'server_tls', 'server_user', 'server_tls_user');
126

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

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

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

    
146
function openvpn_build_mode_list() {
147
	global $openvpn_server_modes;
148

    
149
	$list = array();
150

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

    
155
	return($list);
156
}
157

    
158
function openvpn_build_if_list() {
159
	$list = array();
160

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

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

    
180
		$interfaces[$name] = "GW Group {$name}";
181
	}
182

    
183
	$interfaces['lo0'] = "Localhost";
184
	$interfaces['any'] = "any";
185

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

    
190
	return($list);
191
}
192

    
193
function openvpn_build_crl_list() {
194
	global $a_crl;
195

    
196
	$list = array('' => 'None');
197

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

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

    
206
		$list[$crl['refid']] = $crl['descr'] . $caname;
207
	}
208

    
209
	return($list);
210
}
211

    
212
function openvpn_build_cert_list($include_none = false, $prioritize_server_certs = false) {
213
	global $a_cert;
214

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

    
221
	$non_server_list = array();
222

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

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

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

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

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

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

    
267
function openvpn_build_bridge_list() {
268
	$list = array();
269

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

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

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

    
285
	return($list);
286
}
287

    
288
function openvpn_create_key() {
289

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

    
295
	$rslt = stream_get_contents($fp);
296
	pclose($fp);
297

    
298
	return $rslt;
299
}
300

    
301
function openvpn_create_dhparams($bits) {
302

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

    
308
	$rslt = stream_get_contents($fp);
309
	pclose($fp);
310

    
311
	return $rslt;
312
}
313

    
314
function openvpn_vpnid_used($vpnid) {
315
	global $config;
316

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

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

    
333
	return false;
334
}
335

    
336
function openvpn_vpnid_next() {
337

    
338
	$vpnid = 1;
339
	while (openvpn_vpnid_used($vpnid)) {
340
		$vpnid++;
341
	}
342

    
343
	return $vpnid;
344
}
345

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

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

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

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

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

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

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

    
383
	return 0;
384
}
385

    
386
function openvpn_port_next($prot, $interface = "wan") {
387

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

    
396
	return $port;
397
}
398

    
399
function openvpn_get_cipherlist() {
400

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

    
413
function openvpn_get_digestlist() {
414

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

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

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

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

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

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

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

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

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

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

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

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

    
540
function openvpn_add_dhcpopts(& $settings, & $conf) {
541

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

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

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

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

    
570
	if ($settings['netbios_enable']) {
571

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

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

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

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

    
596
function openvpn_add_custom(& $settings, & $conf) {
597

    
598
	if ($settings['custom_options']) {
599

    
600
		$options = explode(';', $settings['custom_options']);
601

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

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

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

    
622
	$conf .= "{$directive} {$fpath} {$opt}\n";
623
}
624

    
625
function openvpn_reconfigure($mode, $settings) {
626
	global $g, $config, $openvpn_tls_server_modes;
627

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

    
641
	$vpnid = $settings['vpnid'];
642
	$mode_id = $mode.$vpnid;
643

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

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

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

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

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

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

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

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

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

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

    
712

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

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

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

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

    
762
	// server specific settings
763
	if ($mode == 'server') {
764

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

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

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

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

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

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

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

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

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

    
906
	// client specific settings
907

    
908
	if ($mode == 'client') {
909

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1076
	openvpn_add_custom($settings, $conf);
1077

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

    
1093
function openvpn_restart($mode, $settings) {
1094
	global $g, $config;
1095

    
1096
	$vpnid = $settings['vpnid'];
1097
	$mode_id = $mode.$vpnid;
1098

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

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

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

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

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

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

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

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

    
1146
	if (!platform_booting()) {
1147
		send_event("filter reload");
1148
	}
1149
}
1150

    
1151
function openvpn_delete($mode, & $settings) {
1152
	global $g, $config;
1153

    
1154
	$vpnid = $settings['vpnid'];
1155
	$mode_id = $mode.$vpnid;
1156

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

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

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

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

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

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

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

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

    
1192
function openvpn_resync_csc(& $settings) {
1193
	global $g, $config, $openvpn_tls_server_modes;
1194

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

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

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

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

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

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

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

    
1234
	openvpn_add_dhcpopts($settings, $conf);
1235

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

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

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

    
1273
function openvpn_resync_csc_all() {
1274
	global $config;
1275
	if (is_array($config['openvpn']['openvpn-csc'])) {
1276
		foreach ($config['openvpn']['openvpn-csc'] as & $settings) {
1277
			openvpn_resync_csc($settings);
1278
		}
1279
	}
1280
}
1281

    
1282
function openvpn_delete_csc(& $settings) {
1283
	global $g, $config, $openvpn_tls_server_modes;
1284
	$csc_base_path = "{$g['varetc_path']}/openvpn-csc";
1285
	if (empty($settings['server_list'])) {
1286
		$csc_server_list = array();
1287
	} else {
1288
		$csc_server_list = explode(",", $settings['server_list']);
1289
	}
1290

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

    
1307
// Resync the configuration and restart the VPN
1308
function openvpn_resync($mode, $settings) {
1309
	openvpn_reconfigure($mode, $settings);
1310
	openvpn_restart($mode, $settings);
1311
}
1312

    
1313
// Resync and restart all VPNs
1314
function openvpn_resync_all($interface = "") {
1315
	global $g, $config;
1316

    
1317
	openvpn_create_dirs();
1318

    
1319
	if (!is_array($config['openvpn'])) {
1320
		$config['openvpn'] = array();
1321
	}
1322

    
1323
/*
1324
	if (!$config['openvpn']['dh-parameters']) {
1325
		echo "Configuring OpenVPN Parameters ...\n";
1326
		$dh_parameters = openvpn_create_dhparams(1024);
1327
		$dh_parameters = base64_encode($dh_parameters);
1328
		$config['openvpn']['dh-parameters'] = $dh_parameters;
1329
		write_config("OpenVPN DH parameters");
1330
	}
1331

    
1332
	$path_ovdh = $g['varetc_path']."/openvpn/dh-parameters";
1333
	if (!file_exists($path_ovdh)) {
1334
		$dh_parameters = $config['openvpn']['dh-parameters'];
1335
		$dh_parameters = base64_decode($dh_parameters);
1336
		file_put_contents($path_ovdh, $dh_parameters);
1337
	}
1338
*/
1339
	if ($interface <> "") {
1340
		log_error(sprintf(gettext("Resyncing OpenVPN instances for interface %s."), convert_friendly_interface_to_friendly_descr($interface)));
1341
	} else {
1342
		log_error(gettext("Resyncing OpenVPN instances."));
1343
	}
1344

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

    
1354
	if (is_array($config['openvpn']['openvpn-client'])) {
1355
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1356
			if ($interface <> "" && $interface != $settings['interface']) {
1357
				continue;
1358
			}
1359
			openvpn_resync('client', $settings);
1360
		}
1361
	}
1362

    
1363
	openvpn_resync_csc_all();
1364

    
1365
}
1366

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

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

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

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

    
1392
	} else {
1393
		log_error(gettext("openvpn_resync_gwgroup called with null gwgroup parameter."));
1394
	}
1395
}
1396

    
1397
function openvpn_get_active_servers($type="multipoint") {
1398
	global $config, $g;
1399

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

    
1407
			$prot = $settings['protocol'];
1408
			$port = $settings['local_port'];
1409

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

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

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

    
1441
		/* send our status request */
1442
		fputs($fp, "status 2\n");
1443

    
1444
		/* recv all response lines */
1445
		while (!feof($fp)) {
1446

    
1447
			/* read the next line */
1448
			$line = fgets($fp, 1024);
1449

    
1450
			$info = stream_get_meta_data($fp);
1451
			if ($info['timed_out']) {
1452
				break;
1453
			}
1454

    
1455
			/* parse header list line */
1456
			if (strstr($line, "HEADER")) {
1457
				continue;
1458
			}
1459

    
1460
			/* parse end of output line */
1461
			if (strstr($line, "END") || strstr($line, "ERROR")) {
1462
				break;
1463
			}
1464

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

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

    
1504
function openvpn_get_active_clients() {
1505
	global $config, $g;
1506

    
1507
	$clients = array();
1508
	if (is_array($config['openvpn']['openvpn-client'])) {
1509
		foreach ($config['openvpn']['openvpn-client'] as & $settings) {
1510

    
1511
			if (empty($settings) || isset($settings['disable'])) {
1512
				continue;
1513
			}
1514

    
1515
			$prot = $settings['protocol'];
1516
			$port = ($settings['local_port']) ? ":{$settings['local_port']}" : "";
1517

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

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

    
1531
			$clients[] = openvpn_get_client_status($client, $socket);
1532
		}
1533
	}
1534
	return $clients;
1535
}
1536

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

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

    
1551
			$info = stream_get_meta_data($fp);
1552
			if ($info['timed_out']) {
1553
				break;
1554
			}
1555

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

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

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

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

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

    
1596
				$info = stream_get_meta_data($fp);
1597
				if ($info['timed_out']) {
1598
					break;
1599
				}
1600

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

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

    
1611
				/* parse end of output line */
1612
				if (strstr($line, "END")) {
1613
					break;
1614
				}
1615
			}
1616
		}
1617

    
1618
		fclose($fp);
1619

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

    
1630
function openvpn_kill_client($port, $remipp) {
1631
	global $g;
1632

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

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

    
1647
			$info = stream_get_meta_data($fp);
1648
			if ($info['timed_out']) {
1649
				break;
1650
			}
1651

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

    
1666
function openvpn_refresh_crls() {
1667
	global $g, $config;
1668

    
1669
	openvpn_create_dirs();
1670

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

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

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

    
1722
function openvpn_get_interface_ip($ip, $cidr) {
1723
	$subnet = gen_subnetv4($ip, $cidr);
1724
	$ip1 = ip_after($subnet);
1725
	$ip2 = ip_after($ip1);
1726
	return array($ip1, $ip2);
1727
}
1728

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

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

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

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

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

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

    
1781
		if ($push) {
1782
			$routes .= "push \"{$route}\"\n";
1783
		} else {
1784
			$routes .= "{$route}\n";
1785
		}
1786
	}
1787
	return $routes;
1788
}
1789

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

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

    
1806
function openvpn_get_settings($mode, $vpnid) {
1807
	global $config;
1808

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

    
1815
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1816
				return $settings;
1817
			}
1818
		}
1819
	}
1820

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

    
1827
			if ($vpnid != 0 && $vpnid == $settings['vpnid']) {
1828
				return $settings;
1829
			}
1830
		}
1831
	}
1832

    
1833
	return array();
1834
}
1835

    
1836
function openvpn_restart_by_vpnid($mode, $vpnid) {
1837
	$settings = openvpn_get_settings($mode, $vpnid);
1838
	openvpn_restart($mode, $settings);
1839
}
1840

    
1841
?>
(37-37/65)