Project

General

Profile

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

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

    
9
	originally part of m0n0wall (http://m0n0.ch/wall)
10
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
	All rights reserved.
12

    
13
	Redistribution and use in source and binary forms, with or without
14
	modification, are permitted provided that the following conditions are met:
15

    
16
	1. Redistributions of source code must retain the above copyright notice,
17
	   this list of conditions and the following disclaimer.
18

    
19
	2. Redistributions in binary form must reproduce the above copyright
20
	   notice, this list of conditions and the following disclaimer in
21
	   the documentation and/or other materials provided with the
22
	   distribution.
23

    
24
	3. All advertising materials mentioning features or use of this software
25
	   must display the following acknowledgment:
26
	   "This product includes software developed by the pfSense Project
27
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
28

    
29
	4. The names "pfSense" and "pfSense Project" must not be used to
30
	   endorse or promote products derived from this software without
31
	   prior written permission. For written permission, please contact
32
	   coreteam@pfsense.org.
33

    
34
	5. Products derived from this software may not be called "pfSense"
35
	   nor may "pfSense" appear in their names without prior written
36
	   permission of the Electric Sheep Fencing, LLC.
37

    
38
	6. Redistributions of any form whatsoever must retain the following
39
	   acknowledgment:
40

    
41
	"This product includes software developed by the pfSense Project
42
	for use in the pfSense software distribution (http://www.pfsense.org/).
43

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

    
58
function activate_powerd() {
59
	global $config, $g;
60

    
61
	if (is_process_running("powerd")) {
62
		exec("/usr/bin/killall powerd");
63
	}
64
	if (isset($config['system']['powerd_enable'])) {
65
		if ($g["platform"] == "nanobsd") {
66
			exec("/sbin/kldload cpufreq");
67
		}
68

    
69
		$ac_mode = "hadp";
70
		if (!empty($config['system']['powerd_ac_mode'])) {
71
			$ac_mode = $config['system']['powerd_ac_mode'];
72
		}
73

    
74
		$battery_mode = "hadp";
75
		if (!empty($config['system']['powerd_battery_mode'])) {
76
			$battery_mode = $config['system']['powerd_battery_mode'];
77
		}
78

    
79
		$normal_mode = "hadp";
80
		if (!empty($config['system']['powerd_normal_mode'])) {
81
			$normal_mode = $config['system']['powerd_normal_mode'];
82
		}
83

    
84
		mwexec("/usr/sbin/powerd -b $battery_mode -a $ac_mode -n $normal_mode");
85
	}
86
}
87

    
88
function get_default_sysctl_value($id) {
89
	global $sysctls;
90

    
91
	if (isset($sysctls[$id])) {
92
		return $sysctls[$id];
93
	}
94
}
95

    
96
function get_sysctl_descr($sysctl) {
97
	unset($output);
98
	$_gb = exec("/sbin/sysctl -nd {$sysctl}", $output);
99

    
100
	return $output[0];
101
}
102

    
103
function system_get_sysctls() {
104
	global $config, $sysctls;
105

    
106
	$disp_sysctl = array();
107
	$disp_cache = array();
108
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
109
		foreach ($config['sysctl']['item'] as $id => $tunable) {
110
			if ($tunable['value'] == "default") {
111
				$value = get_default_sysctl_value($tunable['tunable']);
112
			} else {
113
				$value = $tunable['value'];
114
			}
115

    
116
			$disp_sysctl[$id] = $tunable;
117
			$disp_sysctl[$id]['modified'] = true;
118
			$disp_cache[$tunable['tunable']] = 'set';
119
		}
120
	}
121

    
122
	foreach ($sysctls as $sysctl => $value) {
123
		if (isset($disp_cache[$sysctl])) {
124
			continue;
125
		}
126

    
127
		$disp_sysctl[$sysctl] = array('tunable' => $sysctl, 'value' => $value, 'descr' => get_sysctl_descr($sysctl));
128
	}
129
	unset($disp_cache);
130
	return $disp_sysctl;
131
}
132

    
133
function activate_sysctls() {
134
	global $config, $g, $sysctls;
135

    
136
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
137
		foreach ($config['sysctl']['item'] as $tunable) {
138
			if ($tunable['value'] == "default") {
139
				$value = get_default_sysctl_value($tunable['tunable']);
140
			} else {
141
				$value = $tunable['value'];
142
			}
143

    
144
			$sysctls[$tunable['tunable']] = $value;
145
		}
146
	}
147

    
148
	set_sysctl($sysctls);
149
}
150

    
151
function system_resolvconf_generate($dynupdate = false) {
152
	global $config, $g;
153

    
154
	if (isset($config['system']['developerspew'])) {
155
		$mt = microtime();
156
		echo "system_resolvconf_generate() being called $mt\n";
157
	}
158

    
159
	$syscfg = $config['system'];
160

    
161
	if ((((isset($config['dnsmasq']['enable'])) &&
162
	      (empty($config['dnsmasq']['port']) || $config['dnsmasq']['port'] == "53") &&
163
	      (empty($config['dnsmasq']['interface']) ||
164
	       in_array("lo0", explode(",", $config['dnsmasq']['interface'])))) ||
165
	     ((isset($config['unbound']['enable'])) &&
166
	      (empty($config['unbound']['port']) || $config['unbound']['port'] == "53") &&
167
	      (empty($config['unbound']['active_interface']) ||
168
	       in_array("lo0", explode(",", $config['unbound']['active_interface'])) ||
169
	       in_array("all", explode(",", $config['unbound']['active_interface']), true)))) &&
170
	     (!isset($config['system']['dnslocalhost']))) {
171
		$resolvconf .= "nameserver 127.0.0.1\n";
172
	}
173

    
174
	if (isset($syscfg['dnsallowoverride'])) {
175
		/* get dynamically assigned DNS servers (if any) */
176
		$ns = array_unique(get_searchdomains());
177
		foreach ($ns as $searchserver) {
178
			if ($searchserver) {
179
				$resolvconf .= "search {$searchserver}\n";
180
			}
181
		}
182
		$ns = array_unique(get_nameservers());
183
		foreach ($ns as $nameserver) {
184
			if ($nameserver) {
185
				$resolvconf .= "nameserver $nameserver\n";
186
			}
187
		}
188
	} else {
189
		$ns = array();
190
		// Do not create blank search/domain lines, it can break tools like dig.
191
		if ($syscfg['domain']) {
192
			$resolvconf .= "search {$syscfg['domain']}\n";
193
		}
194
	}
195
	if (is_array($syscfg['dnsserver'])) {
196
		foreach ($syscfg['dnsserver'] as $sys_dnsserver) {
197
			if ($sys_dnsserver && (!in_array($sys_dnsserver, $ns))) {
198
				$resolvconf .= "nameserver $sys_dnsserver\n";
199
			}
200
		}
201
	}
202

    
203
	// Add EDNS support
204
	if (isset($config['unbound']['enable']) && isset($config['unbound']['edns'])) {
205
		$resolvconf .= "options edns0\n";
206
	}
207

    
208
	$dnslock = lock('resolvconf', LOCK_EX);
209

    
210
	$fd = fopen("{$g['varetc_path']}/resolv.conf", "w");
211
	if (!$fd) {
212
		printf("Error: cannot open resolv.conf in system_resolvconf_generate().\n");
213
		unlock($dnslock);
214
		return 1;
215
	}
216

    
217
	fwrite($fd, $resolvconf);
218
	fclose($fd);
219

    
220
	// Prevent resolvconf(8) from rewriting our resolv.conf
221
	$fd = fopen("{$g['varetc_path']}/resolvconf.conf", "w");
222
	if (!$fd) {
223
		printf("Error: cannot open resolvconf.conf in system_resolvconf_generate().\n");
224
		return 1;
225
	}
226
	fwrite($fd, "resolv_conf=\"/dev/null\"\n");
227
	fclose($fd);
228

    
229
	if (!platform_booting()) {
230
		/* restart dhcpd (nameservers may have changed) */
231
		if (!$dynupdate) {
232
			services_dhcpd_configure();
233
		}
234
	}
235

    
236
	/* setup static routes for DNS servers. */
237
	for ($dnscounter=1; $dnscounter<5; $dnscounter++) {
238
		/* setup static routes for dns servers */
239
		$dnsgw = "dns{$dnscounter}gw";
240
		if (isset($config['system'][$dnsgw])) {
241
			if (empty($config['system'][$dnsgw]) ||
242
			    $config['system'][$dnsgw] == "none") {
243
				continue;
244
			}
245
			$gwname = $config['system'][$dnsgw];
246
			$gatewayip = lookup_gateway_ip_by_name($gwname);
247
			$inet6 = is_ipaddrv6($gatewayip) ? '-inet6 ' : '';
248
			/* dns server array starts at 0 */
249
			$dnsserver = $syscfg['dnsserver'][$dnscounter - 1];
250

    
251
			if (is_ipaddr($gatewayip)) {
252
				$cmd = 'change';
253
			} else {
254
				/* Remove old route when disable gw */
255
				$cmd = 'delete';
256
				$gatewayip = '';
257
			}
258

    
259
			mwexec("/sbin/route {$cmd} -host {$inet6}{$dnsserver} {$gatewayip}");
260
			if (isset($config['system']['route-debug'])) {
261
				$mt = microtime();
262
				log_error("ROUTING debug: $mt - route {$cmd} -host {$inet6}{$dnsserver} {$gatewayip}");
263
			}
264
		}
265
	}
266

    
267
	unlock($dnslock);
268

    
269
	return 0;
270
}
271

    
272
function get_searchdomains() {
273
	global $config, $g;
274

    
275
	$master_list = array();
276

    
277
	// Read in dhclient nameservers
278
	$search_list = glob("/var/etc/searchdomain_*");
279
	if (is_array($search_list)) {
280
		foreach ($search_list as $fdns) {
281
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
282
			if (!is_array($contents)) {
283
				continue;
284
			}
285
			foreach ($contents as $dns) {
286
				if (is_hostname($dns)) {
287
					$master_list[] = $dns;
288
				}
289
			}
290
		}
291
	}
292

    
293
	return $master_list;
294
}
295

    
296
function get_nameservers() {
297
	global $config, $g;
298
	$master_list = array();
299

    
300
	// Read in dhclient nameservers
301
	$dns_lists = glob("/var/etc/nameserver_*");
302
	if (is_array($dns_lists)) {
303
		foreach ($dns_lists as $fdns) {
304
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
305
			if (!is_array($contents)) {
306
				continue;
307
			}
308
			foreach ($contents as $dns) {
309
				if (is_ipaddr($dns)) {
310
					$master_list[] = $dns;
311
				}
312
			}
313
		}
314
	}
315

    
316
	// Read in any extra nameservers
317
	if (file_exists("/var/etc/nameservers.conf")) {
318
		$dns_s = file("/var/etc/nameservers.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
319
		if (is_array($dns_s)) {
320
			foreach ($dns_s as $dns) {
321
				if (is_ipaddr($dns)) {
322
					$master_list[] = $dns;
323
				}
324
			}
325
		}
326
	}
327

    
328
	return $master_list;
329
}
330

    
331
function system_hosts_generate() {
332
	global $config, $g;
333
	if (isset($config['system']['developerspew'])) {
334
		$mt = microtime();
335
		echo "system_hosts_generate() being called $mt\n";
336
	}
337

    
338
	$syscfg = $config['system'];
339
	if (isset($config['unbound']) && isset($config['unbound']['enable'])) {
340
		$dnsmasqcfg = $config['unbound'];
341
	} else {
342
		$dnsmasqcfg = $config['dnsmasq'];
343
	}
344

    
345
	$hosts = "127.0.0.1	localhost localhost.{$syscfg['domain']}\n";
346
	$hosts .= "::1		localhost localhost.{$syscfg['domain']}\n";
347
	$lhosts = "";
348
	$dhosts = "";
349

    
350
	if ($config['interfaces']['lan']) {
351
		$cfgip = get_interface_ip("lan");
352
		if (is_ipaddr($cfgip)) {
353
			$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
354
		}
355
		$cfgipv6 = get_interface_ipv6("lan");
356
		if (is_ipaddrv6($cfgipv6)) {
357
			$hosts .= "{$cfgipv6}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
358
		}
359
	} else {
360
		$sysiflist = get_configured_interface_list();
361
		$hosts_if_found = false;
362
		foreach ($sysiflist as $sysif) {
363
			if (!interface_has_gateway($sysif)) {
364
				$cfgip = get_interface_ip($sysif);
365
				if (is_ipaddr($cfgip)) {
366
					$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
367
					$hosts_if_found = true;
368
				}
369
				$cfgipv6 = get_interface_ipv6($sysif);
370
				if (is_ipaddrv6($cfgipv6)) {
371
					$hosts .= "{$cfgipv6}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
372
					$hosts_if_found = true;
373
				}
374
				if ($hosts_if_found == true) {
375
					break;
376
				}
377
			}
378
		}
379
	}
380

    
381
	if (isset($dnsmasqcfg['enable'])) {
382
		if (!is_array($dnsmasqcfg['hosts'])) {
383
			$dnsmasqcfg['hosts'] = array();
384
		}
385

    
386
		foreach ($dnsmasqcfg['hosts'] as $host) {
387
			if ($host['host'] || $host['host'] == "0") {
388
				$lhosts .= "{$host['ip']}	{$host['host']}.{$host['domain']} {$host['host']}\n";
389
			} else {
390
				$lhosts .= "{$host['ip']}	{$host['domain']}\n";
391
			}
392
			if (!is_array($host['aliases']) || !is_array($host['aliases']['item'])) {
393
				continue;
394
			}
395
			foreach ($host['aliases']['item'] as $alias) {
396
				if ($alias['host'] || $alias['host'] == "0") {
397
					$lhosts .= "{$host['ip']}	{$alias['host']}.{$alias['domain']} {$alias['host']}\n";
398
				} else {
399
					$lhosts .= "{$host['ip']}	{$alias['domain']}\n";
400
				}
401
			}
402
		}
403
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpd'])) {
404
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
405
				if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable'])) {
406
					foreach ($dhcpifconf['staticmap'] as $host) {
407
						if ($host['ipaddr'] && $host['hostname'] && $host['domain']) {
408
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
409
						} else if ($host['ipaddr'] && $host['hostname'] && $dhcpifconf['domain']) {
410
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
411
						} else if ($host['ipaddr'] && $host['hostname']) {
412
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
413
						}
414
					}
415
				}
416
			}
417
		}
418
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpdv6'])) {
419
			foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) {
420
				if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable'])) {
421
					foreach ($dhcpifconf['staticmap'] as $host) {
422
						if ($host['ipaddrv6'] && $host['hostname'] && $host['domain']) {
423
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
424
						} else if ($host['ipaddrv6'] && $host['hostname'] && $dhcpifconf['domain']) {
425
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
426
						} else if ($host['ipaddrv6'] && $host['hostname']) {
427
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
428
						}
429
					}
430
				}
431
			}
432
		}
433

    
434
		if (isset($dnsmasqcfg['dhcpfirst'])) {
435
			$hosts .= $dhosts . $lhosts;
436
		} else {
437
			$hosts .= $lhosts . $dhosts;
438
		}
439
	}
440

    
441
	/*
442
	 * Do not remove this because dhcpleases monitors with kqueue it needs to be
443
	 * killed before writing to hosts files.
444
	 */
445
	if (file_exists("{$g['varrun_path']}/dhcpleases.pid")) {
446
		sigkillbypid("{$g['varrun_path']}/dhcpleases.pid", "TERM");
447
		@unlink("{$g['varrun_path']}/dhcpleases.pid");
448
	}
449
	$fd = fopen("{$g['varetc_path']}/hosts", "w");
450
	if (!$fd) {
451
		log_error("Error: cannot open hosts file in system_hosts_generate().\n");
452
		return 1;
453
	}
454
	fwrite($fd, $hosts);
455
	fclose($fd);
456

    
457
	if (isset($config['unbound']['enable'])) {
458
		require_once("unbound.inc");
459
		unbound_hosts_generate();
460
	}
461

    
462
	return 0;
463
}
464

    
465
function system_dhcpleases_configure() {
466
	global $config, $g;
467

    
468
	/* Start the monitoring process for dynamic dhcpclients. */
469
	if ((isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcp'])) ||
470
	    (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcp']))) {
471
		/* Make sure we do not error out */
472
		mwexec("/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db");
473
		if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases")) {
474
			@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
475
		}
476

    
477
		if (isset($config['unbound']['enable'])) {
478
			$dns_pid = "unbound.pid";
479
			$unbound_conf = "-u {$g['unbound_chroot_path']}/dhcpleases_entries.conf";
480
		} else {
481
			$dns_pid = "dnsmasq.pid";
482
			$unbound_conf = "";
483
		}
484

    
485
		$pidfile = "{$g['varrun_path']}/dhcpleases.pid";
486
		if (isvalidpid($pidfile)) {
487
			/* Make sure dhcpleases is using correct unbound or dnsmasq */
488
			$_gb = exec("/bin/pgrep -F {$pidfile} -f {$dns_pid}", $output, $retval);
489
			if (intval($retval) == 0) {
490
				sigkillbypid($pidfile, "HUP");
491
				return;
492
			} else {
493
				sigkillbypid($pidfile, "TERM");
494
			}
495
		}
496

    
497
		/* To ensure we do not start multiple instances of dhcpleases, perform some clean-up first. */
498
		if (is_process_running("dhcpleases")) {
499
			sigkillbyname('dhcpleases', "TERM");
500
		}
501
		@unlink($pidfile);
502
		mwexec("/usr/local/sbin/dhcpleases -l {$g['dhcpd_chroot_path']}/var/db/dhcpd.leases -d {$config['system']['domain']} -p {$g['varrun_path']}/{$dns_pid} {$unbound_conf} -h {$g['varetc_path']}/hosts");
503
	} else {
504
		sigkillbypid($pidfile, "TERM");
505
		@unlink($pidfile);
506
	}
507
}
508

    
509
function system_hostname_configure() {
510
	global $config, $g;
511
	if (isset($config['system']['developerspew'])) {
512
		$mt = microtime();
513
		echo "system_hostname_configure() being called $mt\n";
514
	}
515

    
516
	$syscfg = $config['system'];
517

    
518
	/* set hostname */
519
	$status = mwexec("/bin/hostname " .
520
		escapeshellarg("{$syscfg['hostname']}.{$syscfg['domain']}"));
521

    
522
	/* Setup host GUID ID.  This is used by ZFS. */
523
	mwexec("/etc/rc.d/hostid start");
524

    
525
	return $status;
526
}
527

    
528
function system_routing_configure($interface = "") {
529
	global $config, $g;
530

    
531
	if (isset($config['system']['developerspew'])) {
532
		$mt = microtime();
533
		echo "system_routing_configure() being called $mt\n";
534
	}
535

    
536
	$gatewayip = "";
537
	$interfacegw = "";
538
	$gatewayipv6 = "";
539
	$interfacegwv6 = "";
540
	$foundgw = false;
541
	$foundgwv6 = false;
542
	/* tack on all the hard defined gateways as well */
543
	if (is_array($config['gateways']['gateway_item'])) {
544
		array_map('unlink', glob("{$g['tmp_path']}/*_defaultgw{,v6}", GLOB_BRACE));
545
		foreach	($config['gateways']['gateway_item'] as $gateway) {
546
			if (isset($gateway['defaultgw'])) {
547
				if ($foundgw == false && ($gateway['ipprotocol'] != "inet6" && (is_ipaddrv4($gateway['gateway']) || $gateway['gateway'] == "dynamic"))) {
548
					if (strpos($gateway['gateway'], ":")) {
549
						continue;
550
					}
551
					if ($gateway['gateway'] == "dynamic") {
552
						$gateway['gateway'] = get_interface_gateway($gateway['interface']);
553
					}
554
					$gatewayip = $gateway['gateway'];
555
					$interfacegw = $gateway['interface'];
556
					if (!empty($gateway['interface'])) {
557
						$defaultif = get_real_interface($gateway['interface']);
558
						if ($defaultif) {
559
							@file_put_contents("{$g['tmp_path']}/{$defaultif}_defaultgw", $gateway['gateway']);
560
						}
561
					}
562
					$foundgw = true;
563
				} else if ($foundgwv6 == false && ($gateway['ipprotocol'] == "inet6" && (is_ipaddrv6($gateway['gateway']) || $gateway['gateway'] == "dynamic"))) {
564
					if ($gateway['gateway'] == "dynamic") {
565
						$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
566
					}
567
					$gatewayipv6 = $gateway['gateway'];
568
					$interfacegwv6 = $gateway['interface'];
569
					if (!empty($gateway['interface'])) {
570
						$defaultifv6 = get_real_interface($gateway['interface']);
571
						if ($defaultifv6) {
572
							@file_put_contents("{$g['tmp_path']}/{$defaultifv6}_defaultgwv6", $gateway['gateway']);
573
						}
574
					}
575
					$foundgwv6 = true;
576
				}
577
			}
578
			if ($foundgw === true && $foundgwv6 === true) {
579
				break;
580
			}
581
		}
582
	}
583
	if ($foundgw == false) {
584
		$defaultif = get_real_interface("wan");
585
		$interfacegw = "wan";
586
		$gatewayip = get_interface_gateway("wan");
587
		@file_put_contents("{$g['tmp_path']}/{$defaultif}_defaultgw", $gatewayip);
588
	}
589
	if ($foundgwv6 == false) {
590
		$defaultifv6 = get_real_interface("wan");
591
		$interfacegwv6 = "wan";
592
		$gatewayipv6 = get_interface_gateway_v6("wan");
593
		@file_put_contents("{$g['tmp_path']}/{$defaultifv6}_defaultgwv6", $gatewayipv6);
594
	}
595
	$dont_add_route = false;
596
	/* if OLSRD is enabled, allow WAN to house DHCP. */
597
	if (is_array($config['installedpackages']['olsrd'])) {
598
		foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
599
			if (($olsrd['enabledyngw'] == "on") && ($olsrd['enable'] == "on")) {
600
				$dont_add_route = true;
601
				log_error(sprintf(gettext("Not adding default route because OLSR dynamic gateway is enabled.")));
602
				break;
603
			}
604
		}
605
	}
606

    
607
	$gateways_arr = return_gateways_array(false, true);
608
	foreach ($gateways_arr as $gateway) {
609
		// setup static interface routes for nonlocal gateways
610
		if (isset($gateway["nonlocalgateway"])) {
611
			$srgatewayip = $gateway['gateway'];
612
			$srinterfacegw = $gateway['interface'];
613
			if (is_ipaddr($srgatewayip) && !empty($srinterfacegw)) {
614
				$inet = (!is_ipaddrv4($srgatewayip) ? "-inet6" : "-inet");
615
				$cmd = "/sbin/route change {$inet} " . escapeshellarg($srgatewayip) . " ";
616
				mwexec($cmd . "-iface " . escapeshellarg($srinterfacegw));
617
				if (isset($config['system']['route-debug'])) {
618
					$mt = microtime();
619
					log_error("ROUTING debug: $mt - $cmd -iface $srinterfacegw ");
620
				}
621
			}
622
		}
623
	}
624

    
625
	if ($dont_add_route == false) {
626
		if (!empty($interface) && $interface != $interfacegw) {
627
			;
628
		} else if (is_ipaddrv4($gatewayip)) {
629
			log_error("ROUTING: setting default route to $gatewayip");
630
			mwexec("/sbin/route change -inet default " . escapeshellarg($gatewayip));
631
		}
632

    
633
		if (!empty($interface) && $interface != $interfacegwv6) {
634
			;
635
		} else if (is_ipaddrv6($gatewayipv6)) {
636
			$ifscope = "";
637
			if (is_linklocal($gatewayipv6) && !strpos($gatewayipv6, '%')) {
638
				$ifscope = "%{$defaultifv6}";
639
			}
640
			log_error("ROUTING: setting IPv6 default route to {$gatewayipv6}{$ifscope}");
641
			mwexec("/sbin/route change -inet6 default " . escapeshellarg("{$gatewayipv6}{$ifscope}"));
642
		}
643
	}
644

    
645
	system_staticroutes_configure($interface, false);
646

    
647
	return 0;
648
}
649

    
650
function system_staticroutes_configure($interface = "", $update_dns = false) {
651
	global $config, $g, $aliastable;
652

    
653
	$filterdns_list = array();
654

    
655
	$static_routes = get_staticroutes(false, true);
656
	if (count($static_routes)) {
657
		$gateways_arr = return_gateways_array(false, true);
658

    
659
		foreach ($static_routes as $rtent) {
660
			if (empty($gateways_arr[$rtent['gateway']])) {
661
				log_error(sprintf(gettext("Static Routes: Gateway IP could not be found for %s"), $rtent['network']));
662
				continue;
663
			}
664
			$gateway = $gateways_arr[$rtent['gateway']];
665
			if (!empty($interface) && $interface != $gateway['friendlyiface']) {
666
				continue;
667
			}
668

    
669
			$gatewayip = $gateway['gateway'];
670
			$interfacegw = $gateway['interface'];
671

    
672
			$blackhole = "";
673
			if (!strcasecmp("Null", substr($rtent['gateway'], 0, 3))) {
674
				$blackhole = "-blackhole";
675
			}
676

    
677
			if (!is_fqdn($rtent['network']) && !is_subnet($rtent['network'])) {
678
				continue;
679
			}
680

    
681
			$dnscache = array();
682
			if ($update_dns === true) {
683
				if (is_subnet($rtent['network'])) {
684
					continue;
685
				}
686
				$dnscache = explode("\n", trim(compare_hostname_to_dnscache($rtent['network'])));
687
				if (empty($dnscache)) {
688
					continue;
689
				}
690
			}
691

    
692
			if (is_subnet($rtent['network'])) {
693
				$ips = array($rtent['network']);
694
			} else {
695
				if (!isset($rtent['disabled'])) {
696
					$filterdns_list[] = $rtent['network'];
697
				}
698
				$ips = add_hostname_to_watch($rtent['network']);
699
			}
700

    
701
			foreach ($dnscache as $ip) {
702
				if (in_array($ip, $ips)) {
703
					continue;
704
				}
705
				mwexec("/sbin/route delete " . escapeshellarg($ip), true);
706
				if (isset($config['system']['route-debug'])) {
707
					$mt = microtime();
708
					log_error("ROUTING debug: $mt - route delete $ip ");
709
				}
710
			}
711

    
712
			if (isset($rtent['disabled'])) {
713
				/* XXX: This can break things by deleting routes that shouldn't be deleted - OpenVPN, dynamic routing scenarios, etc. redmine #3709 */
714
				foreach ($ips as $ip) {
715
					mwexec("/sbin/route delete " . escapeshellarg($ip), true);
716
					if (isset($config['system']['route-debug'])) {
717
						$mt = microtime();
718
						log_error("ROUTING debug: $mt - route delete $ip ");
719
					}
720
				}
721
				continue;
722
			}
723

    
724
			foreach ($ips as $ip) {
725
				if (is_ipaddrv4($ip)) {
726
					$ip .= "/32";
727
				}
728
				// do NOT do the same check here on v6, is_ipaddrv6 returns true when including the CIDR mask. doing so breaks v6 routes
729

    
730
				$inet = (is_subnetv6($ip) ? "-inet6" : "-inet");
731

    
732
				$cmd = "/sbin/route change {$inet} {$blackhole} " . escapeshellarg($ip) . " ";
733

    
734
				if (is_subnet($ip)) {
735
					if (is_ipaddr($gatewayip)) {
736
						mwexec($cmd . escapeshellarg($gatewayip));
737
						if (isset($config['system']['route-debug'])) {
738
							$mt = microtime();
739
							log_error("ROUTING debug: $mt - $cmd $gatewayip");
740
						}
741
					} else if (!empty($interfacegw)) {
742
						mwexec($cmd . "-iface " . escapeshellarg($interfacegw));
743
						if (isset($config['system']['route-debug'])) {
744
							$mt = microtime();
745
							log_error("ROUTING debug: $mt - $cmd -iface $interfacegw ");
746
						}
747
					}
748
				}
749
			}
750
		}
751
		unset($gateways_arr);
752
	}
753
	unset($static_routes);
754

    
755
	if ($update_dns === false) {
756
		if (count($filterdns_list)) {
757
			$interval = 60;
758
			$hostnames = "";
759
			array_unique($filterdns_list);
760
			foreach ($filterdns_list as $hostname) {
761
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload routedns\"'\n";
762
			}
763
			file_put_contents("{$g['varetc_path']}/filterdns-route.hosts", $hostnames);
764
			unset($hostnames);
765

    
766
			if (isvalidpid("{$g['varrun_path']}/filterdns-route.pid")) {
767
				sigkillbypid("{$g['varrun_path']}/filterdns-route.pid", "HUP");
768
			} else {
769
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-route.pid -i {$interval} -c {$g['varetc_path']}/filterdns-route.hosts -d 1");
770
			}
771
		} else {
772
			killbypid("{$g['varrun_path']}/filterdns-route.pid");
773
			@unlink("{$g['varrun_path']}/filterdns-route.pid");
774
		}
775
	}
776
	unset($filterdns_list);
777

    
778
	return 0;
779
}
780

    
781
function system_routing_enable() {
782
	global $config, $g;
783
	if (isset($config['system']['developerspew'])) {
784
		$mt = microtime();
785
		echo "system_routing_enable() being called $mt\n";
786
	}
787

    
788
	set_sysctl(array(
789
		"net.inet.ip.forwarding" => "1",
790
		"net.inet6.ip6.forwarding" => "1"
791
	));
792

    
793
	return;
794
}
795

    
796
function system_syslogd_fixup_server($server) {
797
	/* If it's an IPv6 IP alone, encase it in brackets */
798
	if (is_ipaddrv6($server)) {
799
		return "[$server]";
800
	} else {
801
		return $server;
802
	}
803
}
804

    
805
function system_syslogd_get_remote_servers($syslogcfg, $facility = "*.*") {
806
	// Rather than repeatedly use the same code, use this function to build a list of remote servers.
807
	$facility .= " ".
808
	$remote_servers = "";
809
	$pad_to  = max(strlen($facility), 56);
810
	$padding = ceil(($pad_to - strlen($facility))/8)+1;
811
	if (isset($syslogcfg['enable'])) {
812
		if ($syslogcfg['remoteserver']) {
813
			$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver']) . "\n";
814
		}
815
		if ($syslogcfg['remoteserver2']) {
816
			$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver2']) . "\n";
817
		}
818
		if ($syslogcfg['remoteserver3']) {
819
			$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver3']) . "\n";
820
		}
821
	}
822
	return $remote_servers;
823
}
824

    
825
function clear_log_file($logfile = "/var/log/system.log", $restart_syslogd = true) {
826
	global $config, $g;
827
	if ($restart_syslogd) {
828
		exec("/usr/bin/killall syslogd");
829
	}
830
	if (isset($config['system']['disablesyslogclog'])) {
831
		unlink($logfile);
832
		touch($logfile);
833
	} else {
834
		$log_size = isset($config['syslog']['logfilesize']) ? $config['syslog']['logfilesize'] : "511488";
835
		$log_size = isset($config['syslog'][basename($logfile, '.log') . '_settings']['logfilesize']) ? $config['syslog'][basename($logfile, '.log') . '_settings']['logfilesize'] : $log_size;
836
		exec("/usr/local/sbin/clog -i -s {$log_size} " . escapeshellarg($logfile));
837
	}
838
	if ($restart_syslogd) {
839
		system_syslogd_start();
840
	}
841
}
842

    
843
function clear_all_log_files($restart = false) {
844
	global $g;
845
	exec("/usr/bin/killall syslogd");
846

    
847
	$log_files = array("system", "filter", "dhcpd", "vpn", "pptps", "poes", "l2tps", "openvpn", "portalauth", "ipsec", "ppp", "relayd", "wireless", "nginx", "ntpd", "gateways", "resolver", "routing");
848
	foreach ($log_files as $lfile) {
849
		clear_log_file("{$g['varlog_path']}/{$lfile}.log", false);
850
	}
851

    
852
	if ($restart) {
853
		system_syslogd_start();
854
		killbyname("dhcpd");
855
		services_dhcpd_configure();
856
	}
857
	return;
858
}
859

    
860
function system_syslogd_start() {
861
	global $config, $g;
862
	if (isset($config['system']['developerspew'])) {
863
		$mt = microtime();
864
		echo "system_syslogd_start() being called $mt\n";
865
	}
866

    
867
	mwexec("/etc/rc.d/hostid start");
868

    
869
	$syslogcfg = $config['syslog'];
870

    
871
	if (platform_booting()) {
872
		echo gettext("Starting syslog...");
873
	}
874

    
875
	// Which logging type are we using this week??
876
	if (isset($config['system']['disablesyslogclog'])) {
877
		$log_directive = "";
878
		$log_create_directive = "/usr/bin/touch ";
879
		$log_size = "";
880
	} else { // Defaults to CLOG
881
		$log_directive = "%";
882
		$log_size = isset($config['syslog']['logfilesize']) ? $config['syslog']['logfilesize'] : "10240";
883
		$log_create_directive = "/usr/local/sbin/clog -i -s ";
884
	}
885

    
886
	$syslogd_extra = "";
887
	if (isset($syslogcfg)) {
888
		$separatelogfacilities = array('ntp', 'ntpd', 'ntpdate', 'charon', 'ipsec_starter', 'openvpn', 'pptps', 'poes', 'l2tps', 'relayd', 'hostapd', 'dnsmasq', 'filterdns', 'unbound', 'dhcpd', 'dhcrelay', 'dhclient', 'dhcp6c', 'dpinger', 'radvd', 'routed', 'olsrd', 'zebra', 'ospfd', 'bgpd', 'miniupnpd', 'filterlog');
889
		$syslogconf = "";
890
		if ($config['installedpackages']['package']) {
891
			foreach ($config['installedpackages']['package'] as $package) {
892
				if ($package['logging']) {
893
					array_push($separatelogfacilities, $package['logging']['facilityname']);
894
					if (!is_file($g['varlog_path'].'/'.$package['logging']['logfilename'])) {
895
						mwexec("{$log_create_directive} {$log_size} {$g['varlog_path']}/{$package['logging']['logfilename']}");
896
					}
897
					$syslogconf .= "!{$package['logging']['facilityname']}\n*.*\t\t\t\t\t\t {$log_directive}{$g['varlog_path']}/{$package['logging']['logfilename']}\n";
898
				}
899
			}
900
		}
901
		$facilitylist = implode(',', array_unique($separatelogfacilities));
902
		$syslogconf .= "!radvd,routed,olsrd,zebra,ospfd,bgpd,miniupnpd\n";
903
		if (!isset($syslogcfg['disablelocallogging'])) {
904
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/routing.log\n";
905
		}
906

    
907
		$syslogconf .= "!ntp,ntpd,ntpdate\n";
908
		if (!isset($syslogcfg['disablelocallogging'])) {
909
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ntpd.log\n";
910
		}
911

    
912
		$syslogconf .= "!ppp\n";
913
		if (!isset($syslogcfg['disablelocallogging'])) {
914
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ppp.log\n";
915
		}
916

    
917
		$syslogconf .= "!pptps\n";
918
		if (!isset($syslogcfg['disablelocallogging'])) {
919
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/pptps.log\n";
920
		}
921

    
922
		$syslogconf .= "!poes\n";
923
		if (!isset($syslogcfg['disablelocallogging'])) {
924
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/poes.log\n";
925
		}
926

    
927
		$syslogconf .= "!l2tps\n";
928
		if (!isset($syslogcfg['disablelocallogging'])) {
929
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/l2tps.log\n";
930
		}
931

    
932
		$syslogconf .= "!charon,ipsec_starter\n";
933
		if (!isset($syslogcfg['disablelocallogging'])) {
934
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ipsec.log\n";
935
		}
936
		if (isset($syslogcfg['vpn'])) {
937
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
938
		}
939

    
940
		$syslogconf .= "!openvpn\n";
941
		if (!isset($syslogcfg['disablelocallogging'])) {
942
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/openvpn.log\n";
943
		}
944
		if (isset($syslogcfg['vpn'])) {
945
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
946
		}
947

    
948
		$syslogconf .= "!dpinger\n";
949
		if (!isset($syslogcfg['disablelocallogging'])) {
950
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/gateways.log\n";
951
		}
952
		if (isset($syslogcfg['dpinger'])) {
953
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
954
		}
955

    
956
		$syslogconf .= "!dnsmasq,filterdns,unbound\n";
957
		if (!isset($syslogcfg['disablelocallogging'])) {
958
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/resolver.log\n";
959
		}
960

    
961
		$syslogconf .= "!dhcpd,dhcrelay,dhclient,dhcp6c\n";
962
		if (!isset($syslogcfg['disablelocallogging'])) {
963
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/dhcpd.log\n";
964
		}
965
		if (isset($syslogcfg['dhcp'])) {
966
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
967
		}
968

    
969
		$syslogconf .= "!relayd\n";
970
		if (!isset($syslogcfg['disablelocallogging'])) {
971
			$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/relayd.log\n";
972
		}
973
		if (isset($syslogcfg['relayd'])) {
974
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
975
		}
976

    
977
		$syslogconf .= "!hostapd\n";
978
		if (!isset($syslogcfg['disablelocallogging'])) {
979
			$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/wireless.log\n";
980
		}
981
		if (isset($syslogcfg['hostapd'])) {
982
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
983
		}
984

    
985
		$syslogconf .= "!filterlog\n";
986
		$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/filter.log\n";
987
		if (isset($syslogcfg['filter'])) {
988
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
989
		}
990

    
991
		$syslogconf .= "!-{$facilitylist}\n";
992
		if (!isset($syslogcfg['disablelocallogging'])) {
993
			$syslogconf .= <<<EOD
994
local3.*							{$log_directive}{$g['varlog_path']}/vpn.log
995
local4.*							{$log_directive}{$g['varlog_path']}/portalauth.log
996
local5.*							{$log_directive}{$g['varlog_path']}/nginx.log
997
local7.*							{$log_directive}{$g['varlog_path']}/dhcpd.log
998
*.notice;kern.debug;lpr.info;mail.crit;daemon.none;news.err;local0.none;local3.none;local4.none;local7.none;security.*;auth.info;authpriv.info;daemon.info	{$log_directive}{$g['varlog_path']}/system.log
999
auth.info;authpriv.info 					|exec /usr/local/sbin/sshlockout_pf 15
1000
*.emerg								*
1001

    
1002
EOD;
1003
		}
1004
		if (isset($syslogcfg['vpn'])) {
1005
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local3.*");
1006
		}
1007
		if (isset($syslogcfg['portalauth'])) {
1008
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local4.*");
1009
		}
1010
		if (isset($syslogcfg['dhcp'])) {
1011
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local7.*");
1012
		}
1013
		if (isset($syslogcfg['system'])) {
1014
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.emerg;*.notice;kern.debug;lpr.info;mail.crit;news.err;local0.none;local3.none;local7.none;security.*;auth.info;authpriv.info;daemon.info");
1015
		}
1016
		if (isset($syslogcfg['logall'])) {
1017
			// Make everything mean everything, including facilities excluded above.
1018
			$syslogconf .= "!*\n";
1019
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
1020
		}
1021

    
1022
		if (isset($syslogcfg['zmqserver'])) {
1023
				$syslogconf .= <<<EOD
1024
*.*								^{$syslogcfg['zmqserver']}
1025

    
1026
EOD;
1027
		}
1028
		/* write syslog.conf */
1029
		if (!@file_put_contents("{$g['varetc_path']}/syslog.conf", $syslogconf)) {
1030
			printf(gettext("Error: cannot open syslog.conf in system_syslogd_start().%s"), "\n");
1031
			unset($syslogconf);
1032
			return 1;
1033
		}
1034
		unset($syslogconf);
1035

    
1036
		// Ensure that the log directory exists
1037
		if (!is_dir("{$g['dhcpd_chroot_path']}/var/run")) {
1038
			exec("/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/run");
1039
		}
1040

    
1041
		$sourceip = "";
1042
		if (!empty($syslogcfg['sourceip'])) {
1043
			if ($syslogcfg['ipproto'] == "ipv6") {
1044
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ipv6($syslogcfg['sourceip']);
1045
				if (!is_ipaddr($ifaddr)) {
1046
					$ifaddr = get_interface_ip($syslogcfg['sourceip']);
1047
				}
1048
			} else {
1049
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ip($syslogcfg['sourceip']);
1050
				if (!is_ipaddr($ifaddr)) {
1051
					$ifaddr = get_interface_ipv6($syslogcfg['sourceip']);
1052
				}
1053
			}
1054
			if (is_ipaddr($ifaddr)) {
1055
				$sourceip = "-b {$ifaddr}";
1056
			}
1057
		}
1058

    
1059
		$syslogd_extra = "-f {$g['varetc_path']}/syslog.conf {$sourceip}";
1060
	}
1061

    
1062
	if (isvalidpid("{$g['varrun_path']}/syslog.pid")) {
1063
		sigkillbypid("{$g['varrun_path']}/syslog.pid", "TERM");
1064
		usleep(100000); // syslogd often doesn't respond to a TERM quickly enough for the starting of syslogd below to be successful
1065
	}
1066

    
1067
	if (isvalidpid("{$g['varrun_path']}/syslog.pid")) {
1068
		// if it still hasn't responded to the TERM, KILL it.
1069
		sigkillbypid("{$g['varrun_path']}/syslog.pid", "KILL");
1070
		usleep(100000);
1071
	}
1072

    
1073

    
1074
	$retval = mwexec_bg("/usr/sbin/syslogd -s -c -c -l {$g['dhcpd_chroot_path']}/var/run/log -P {$g['varrun_path']}/syslog.pid {$syslogd_extra}");
1075

    
1076
	if (platform_booting()) {
1077
		echo gettext("done.") . "\n";
1078
	}
1079

    
1080
	return $retval;
1081
}
1082

    
1083
function system_webgui_create_certificate() {
1084
	global $config, $g;
1085

    
1086
	if (!is_array($config['ca'])) {
1087
		$config['ca'] = array();
1088
	}
1089
	$a_ca =& $config['ca'];
1090
	if (!is_array($config['cert'])) {
1091
		$config['cert'] = array();
1092
	}
1093
	$a_cert =& $config['cert'];
1094
	log_error("Creating SSL Certificate for this host");
1095

    
1096
	$cert = array();
1097
	$cert['refid'] = uniqid();
1098
	$cert['descr'] = gettext("webConfigurator default ({$cert['refid']})");
1099

    
1100
	$dn = array(
1101
		'countryName' => "US",
1102
		'stateOrProvinceName' => "State",
1103
		'localityName' => "Locality",
1104
		'organizationName' => "{$g['product_name']} webConfigurator Self-Signed Certificate",
1105
		'emailAddress' => "admin@{$config['system']['hostname']}.{$config['system']['domain']}",
1106
		'commonName' => "{$config['system']['hostname']}-{$cert['refid']}");
1107
	$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
1108
	if (!cert_create($cert, null, 2048, 2000, $dn, "self-signed", "sha256")) {
1109
		while ($ssl_err = openssl_error_string()) {
1110
			log_error("Error creating WebGUI Certificate: openssl library returns: " . $ssl_err);
1111
		}
1112
		error_reporting($old_err_level);
1113
		return null;
1114
	}
1115
	error_reporting($old_err_level);
1116

    
1117
	$a_cert[] = $cert;
1118
	$config['system']['webgui']['ssl-certref'] = $cert['refid'];
1119
	write_config(gettext("Generated new self-signed HTTPS certificate ({$cert['refid']})"));
1120
	return $cert;
1121
}
1122

    
1123
function system_webgui_start() {
1124
	global $config, $g;
1125

    
1126
	if (platform_booting()) {
1127
		echo gettext("Starting webConfigurator...");
1128
	}
1129

    
1130
	chdir($g['www_path']);
1131

    
1132
	/* defaults */
1133
	$portarg = "80";
1134
	$crt = "";
1135
	$key = "";
1136
	$ca = "";
1137

    
1138
	/* non-standard port? */
1139
	if (isset($config['system']['webgui']['port']) && $config['system']['webgui']['port'] <> "") {
1140
		$portarg = "{$config['system']['webgui']['port']}";
1141
	}
1142

    
1143
	if ($config['system']['webgui']['protocol'] == "https") {
1144
		// Ensure that we have a webConfigurator CERT
1145
		$cert =& lookup_cert($config['system']['webgui']['ssl-certref']);
1146
		if (!is_array($cert) || !$cert['crt'] || !$cert['prv']) {
1147
			$cert = system_webgui_create_certificate();
1148
		}
1149
		$crt = base64_decode($cert['crt']);
1150
		$key = base64_decode($cert['prv']);
1151

    
1152
		if (!$config['system']['webgui']['port']) {
1153
			$portarg = "443";
1154
		}
1155
		$ca = ca_chain($cert);
1156
	}
1157

    
1158
	/* generate nginx configuration */
1159
	system_generate_nginx_config("{$g['varetc_path']}/nginx-webConfigurator.conf",
1160
		$crt, $key, $ca, "nginx-webConfigurator.pid", $portarg, "/usr/local/www/",
1161
		"cert.crt", "cert.key");
1162

    
1163
	/* kill any running nginx */
1164
	killbypid("{$g['varrun_path']}/nginx-webConfigurator.pid");
1165

    
1166
	sleep(1);
1167

    
1168
	@unlink("{$g['varrun_path']}/nginx-webConfigurator.pid");
1169

    
1170
	/* start nginx */
1171
	$res = mwexec("/usr/local/sbin/nginx -c {$g['varetc_path']}/nginx-webConfigurator.conf");
1172

    
1173
	if (platform_booting()) {
1174
		if ($res == 0) {
1175
			echo gettext("done.") . "\n";
1176
		} else {
1177
			echo gettext("failed!") . "\n";
1178
		}
1179
	}
1180

    
1181
	return $res;
1182
}
1183

    
1184
function system_generate_nginx_config($filename,
1185
	$cert,
1186
	$key,
1187
	$ca,
1188
	$pid_file,
1189
	$port = 80,
1190
	$document_root = "/usr/local/www/",
1191
	$cert_location = "cert.crt",
1192
	$key_location = "cert.key",
1193
	$captive_portal = false) {
1194

    
1195
	global $config, $g;
1196

    
1197
	if (isset($config['system']['developerspew'])) {
1198
		$mt = microtime();
1199
		echo "system_generate_nginx_config() being called $mt\n";
1200
	}
1201

    
1202
	if ($captive_portal !== false) {
1203
		$cp_interfaces = explode(",", $config['captiveportal'][$captive_portal]['interface']);
1204
		$cp_hostcheck = "";
1205
		foreach ($cp_interfaces as $cpint) {
1206
			$cpint_ip = get_interface_ip($cpint);
1207
			if (is_ipaddr($cpint_ip)) {
1208
				$cp_hostcheck .= "\t\tif (\$http_host ~* $cpint_ip) {\n";
1209
				$cp_hostcheck .= "\t\t\tset \$cp_redirect no;\n";
1210
				$cp_hostcheck .= "\t\t}\n";
1211
			}
1212
		}
1213
		if (isset($config['captiveportal'][$captive_portal]['httpsname']) &&
1214
		    is_domain($config['captiveportal'][$captive_portal]['httpsname'])) {
1215
			$cp_hostcheck .= "\t\tif (\$http_host ~* {$config['captiveportal'][$captive_portal]['httpsname']}) {\n";
1216
			$cp_hostcheck .= "\t\t\tset \$cp_redirect no;\n";
1217
			$cp_hostcheck .= "\t\t}\n";
1218
		}
1219
		$cp_rewrite = "\t\tif (\$cp_redirect = '') {\n";
1220
		$cp_rewrite .= "\t\t\trewrite	^ /index.php?zone=$captive_portal&redirurl=\$request_uri break;\n";
1221
		$cp_rewrite .= "\t\t}\n";
1222

    
1223
		$maxprocperip = $config['captiveportal'][$captive_portal]['maxprocperip'];
1224
		if (empty($maxprocperip)) {
1225
			$maxprocperip = 10;
1226
		}
1227
		$captive_portal_maxprocperip = "\t\tlimit_conn addr $maxprocperip;\n";
1228

    
1229
	}
1230

    
1231
	if (empty($port)) {
1232
		$nginx_port = "80";
1233
	} else {
1234
		$nginx_port = $port;
1235
	}
1236

    
1237
	$memory = get_memory();
1238
	$realmem = $memory[1];
1239

    
1240
	// Determine web GUI process settings and take into account low memory systems
1241
	if ($realmem < 255) {
1242
		$max_procs = 1;
1243
	} else {
1244
		$max_procs = ($config['system']['webgui']['max_procs']) ? $config['system']['webgui']['max_procs'] : 2;
1245
	}
1246

    
1247
	// Ramp up captive portal max procs, assuming each PHP process can consume up to 64MB RAM
1248
	if ($captive_portal !== false) {
1249
		if ($realmem > 135 and $realmem < 256) {
1250
			$max_procs += 1; // 2 worker processes
1251
		} else if ($realmem > 255 and $realmem < 513) {
1252
			$max_procs += 2; // 3 worker processes
1253
		} else if ($realmem > 512) {
1254
			$max_procs += 4; // 6 worker processes
1255
		}
1256
	}
1257

    
1258
	$nginx_config = <<<EOD
1259
#
1260
# nginx configuration file
1261

    
1262
pid {$g['varrun_path']}/{$pid_file};
1263

    
1264
user  root wheel;
1265
worker_processes  {$max_procs};
1266

    
1267
EOD;
1268

    
1269
if (!isset($config['syslog']['nolognginx'])) {
1270
	$nginx_config .= "error_log  syslog:server=unix:/var/run/log,facility=local5;\n";
1271
}
1272

    
1273
$nginx_config .= <<<EOD
1274

    
1275
events {
1276
    worker_connections  1024;
1277
}
1278

    
1279
http {
1280
	include       /usr/local/etc/nginx/mime.types;
1281
	default_type  application/octet-stream;
1282
	add_header X-Frame-Options SAMEORIGIN;
1283
	server_tokens off;
1284

    
1285
	sendfile        on;
1286
	keepalive_timeout  65;
1287

    
1288
	access_log      syslog:server=unix:/var/run/log,facility=local5 combined;
1289

    
1290
EOD;
1291

    
1292
if ($captive_portal !== false) {
1293
	$nginx_config .= "\tlimit_conn_zone \$binary_remote_addr zone=addr:10m;\n";
1294
}
1295

    
1296
$nginx_config .= <<<EOD
1297

    
1298
	server {
1299
		listen {$nginx_port};
1300
		listen [::]:{$nginx_port};
1301
		client_max_body_size 200m;
1302

    
1303
EOD;
1304

    
1305
	if ($cert <> "" and $key <> "") {
1306
		$nginx_config .= "\t\tssl             on;\n";
1307
		$nginx_config .= "\t\tssl_certificate         {$g['varetc_path']}/{$cert_location};\n";
1308
		$nginx_config .= "\t\tssl_certificate_key     {$g['varetc_path']}/{$key_location};\n";
1309
		$nginx_config .= "\t\tssl_session_timeout     10m;\n";
1310
		$nginx_config .= "\t\tkeepalive_timeout       70;\n";
1311
		$nginx_config .= "\t\tssl_session_cache       shared:SSL:10m;\n";
1312
		$nginx_config .= "\t\tssl_protocols   TLSv1 TLSv1.1 TLSv1.2;\n";
1313
		$nginx_config .= "\t\tssl_ciphers \"EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH\";\n";
1314
		$nginx_config .= "\t\tssl_prefer_server_ciphers       on;\n";
1315
		$nginx_config .= "\t\tadd_header Strict-Transport-Security \"max-age=31536000\";\n";
1316
		$nginx_config .= "\t\tadd_header X-Content-Type-Options nosniff;\n";
1317
		$nginx_config .= "\t\tssl_session_tickets off;\n";
1318
		$nginx_config .= "\t\tssl_stapling on;\n";
1319
		$nginx_config .= "\t\tssl_stapling_verify on;\n";
1320
		$nginx_config .= "\t\tssl_dhparam /etc/dh-parameters.4096;\n";
1321
		$nginx_config .= "\n";
1322
	}
1323

    
1324
	if ($captive_portal !== false) {
1325
		$nginx_config .= <<<EOD
1326
$captive_portal_maxprocperip
1327
$cp_hostcheck
1328
$cp_rewrite
1329

    
1330
EOD;
1331

    
1332
	}
1333

    
1334
	$nginx_config .= <<<EOD
1335
		root "{$document_root}";
1336
		location / {
1337
			index  index.html index.htm index.php;
1338
		}
1339

    
1340
		location ~ \.php$ {
1341
			try_files \$uri =404; #  This line closes a potential security hole
1342
			# ensuring users can't execute uploaded files
1343
			# see: http://forum.nginx.org/read.php?2,88845,page=3
1344
			fastcgi_pass   unix:{$g['varrun_path']}/php-fpm.socket;
1345
			fastcgi_index  index.php;
1346
			fastcgi_param  SCRIPT_FILENAME  \$document_root\$fastcgi_script_name;
1347
			include        /usr/local/etc/nginx/fastcgi_params;
1348
		}
1349
	}
1350

    
1351
EOD;
1352

    
1353
	$cert = str_replace("\r", "", $cert);
1354
	$key = str_replace("\r", "", $key);
1355

    
1356
	$cert = str_replace("\n\n", "\n", $cert);
1357
	$key = str_replace("\n\n", "\n", $key);
1358

    
1359
	if ($cert <> "" and $key <> "") {
1360
		$fd = fopen("{$g['varetc_path']}/{$cert_location}", "w");
1361
		if (!$fd) {
1362
			printf(gettext("Error: cannot open certificate file in system_webgui_start().%s"), "\n");
1363
			return 1;
1364
		}
1365
		chmod("{$g['varetc_path']}/{$cert_location}", 0600);
1366
		if ($ca <> "") {
1367
			$cert_chain = $cert . "\n" . $ca;
1368
		} else {
1369
			$cert_chain = $cert;
1370
		}
1371
		fwrite($fd, $cert_chain);
1372
		fclose($fd);
1373
		$fd = fopen("{$g['varetc_path']}/{$key_location}", "w");
1374
		if (!$fd) {
1375
			printf(gettext("Error: cannot open certificate key file in system_webgui_start().%s"), "\n");
1376
			return 1;
1377
		}
1378
		chmod("{$g['varetc_path']}/{$key_location}", 0600);
1379
		fwrite($fd, $key);
1380
		fclose($fd);
1381
	}
1382

    
1383
	// Add HTTP to HTTPS redirect
1384
	if ($captive_portal === false && $config['system']['webgui']['protocol'] == "https" && !isset($config['system']['webgui']['disablehttpredirect'])) {
1385
		if ($nginx_port != "443") {
1386
			$redirectport = ":{$nginx_port}";
1387
		}
1388
		$nginx_config .= <<<EOD
1389
	server {
1390
		listen 80;
1391
		listen [::]:80;
1392
		rewrite         ^ https://\$http_host$redirectport\$request_uri? permanent;
1393
	}
1394

    
1395
EOD;
1396
	}
1397

    
1398
	$nginx_config .= "}\n";
1399

    
1400
	$fd = fopen("{$filename}", "w");
1401
	if (!$fd) {
1402
		printf(gettext("Error: cannot open %s in system_generate_nginx_config().%s"), $filename, "\n");
1403
		return 1;
1404
	}
1405
	fwrite($fd, $nginx_config);
1406
	fclose($fd);
1407

    
1408
	/* nginx will fail to start if this directory does not exist. */
1409
	safe_mkdir("/var/tmp/nginx/");
1410

    
1411
	return 0;
1412

    
1413
}
1414

    
1415
function system_get_timezone_list() {
1416
	global $g;
1417

    
1418
	$file_list = array_merge(
1419
		glob("/usr/share/zoneinfo/[A-Z]*"),
1420
		glob("/usr/share/zoneinfo/*/*"),
1421
		glob("/usr/share/zoneinfo/*/*/*")
1422
	);
1423

    
1424
	if (empty($file_list)) {
1425
		$file_list[] = $g['default_timezone'];
1426
	} else {
1427
		/* Remove directories from list */
1428
		$file_list = array_filter($file_list, function($v) {
1429
			return !is_dir($v);
1430
		});
1431
	}
1432

    
1433
	/* Remove directory prefix */
1434
	$file_list = str_replace('/usr/share/zoneinfo/', '', $file_list);
1435

    
1436
	sort($file_list);
1437

    
1438
	return $file_list;
1439
}
1440

    
1441
function system_timezone_configure() {
1442
	global $config, $g;
1443
	if (isset($config['system']['developerspew'])) {
1444
		$mt = microtime();
1445
		echo "system_timezone_configure() being called $mt\n";
1446
	}
1447

    
1448
	$syscfg = $config['system'];
1449

    
1450
	if (platform_booting()) {
1451
		echo gettext("Setting timezone...");
1452
	}
1453

    
1454
	/* extract appropriate timezone file */
1455
	$timezone = (isset($syscfg['timezone']) ? $syscfg['timezone'] : $g['default_timezone']);
1456
	conf_mount_rw();
1457
	/* DO NOT remove \n otherwise tzsetup will fail */
1458
	@file_put_contents("/var/db/zoneinfo", $timezone . "\n");
1459
	mwexec("/usr/sbin/tzsetup -r");
1460
	conf_mount_ro();
1461

    
1462
	if (platform_booting()) {
1463
		echo gettext("done.") . "\n";
1464
	}
1465
}
1466

    
1467
function system_ntp_setup_gps($serialport) {
1468
	global $config, $g;
1469
	$gps_device = '/dev/gps0';
1470
	$serialport = '/dev/'.$serialport;
1471

    
1472
	if (!file_exists($serialport)) {
1473
		return false;
1474
	}
1475

    
1476
	conf_mount_rw();
1477
	// Create symlink that ntpd requires
1478
	unlink_if_exists($gps_device);
1479
	@symlink($serialport, $gps_device);
1480

    
1481
	$gpsbaud = '4800';
1482
	if (is_array($config['ntpd']) && is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['speed'])) {
1483
		switch ($config['ntpd']['gps']['speed']) {
1484
			case '16':
1485
				$gpsbaud = '9600';
1486
				break;
1487
			case '32':
1488
				$gpsbaud = '19200';
1489
				break;
1490
			case '48':
1491
				$gpsbaud = '38400';
1492
				break;
1493
			case '64':
1494
				$gpsbaud = '57600';
1495
				break;
1496
			case '80':
1497
				$gpsbaud = '115200';
1498
				break;
1499
		}
1500
	}
1501

    
1502
	/* Configure the serial port for raw IO and set the speed */
1503
	mwexec("stty -f {$serialport}.init raw speed {$gpsbaud}");
1504

    
1505
	/* Send the following to the GPS port to initialize the GPS */
1506
	if (is_array($config['ntpd']) && is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['type'])) {
1507
		$gps_init = base64_decode($config['ntpd']['gps']['initcmd']);
1508
	} else {
1509
		$gps_init = base64_decode('JFBVQlgsNDAsR1NWLDAsMCwwLDAqNTkNCiRQVUJYLDQwLEdMTCwwLDAsMCwwKjVDDQokUFVCWCw0MCxaREEsMCwwLDAsMCo0NA0KJFBVQlgsNDAsVlRHLDAsMCwwLDAqNUUNCiRQVUJYLDQwLEdTViwwLDAsMCwwKjU5DQokUFVCWCw0MCxHU0EsMCwwLDAsMCo0RQ0KJFBVQlgsNDAsR0dBLDAsMCwwLDANCiRQVUJYLDQwLFRYVCwwLDAsMCwwDQokUFVCWCw0MCxSTUMsMCwwLDAsMCo0Ng0KJFBVQlgsNDEsMSwwMDA3LDAwMDMsNDgwMCwwDQokUFVCWCw0MCxaREEsMSwxLDEsMQ==');
1510
	}
1511

    
1512
	/* XXX: Why not file_put_contents to the device */
1513
	@file_put_contents('/tmp/gps.init', $gps_init);
1514
	mwexec("cat /tmp/gps.init > {$serialport}");
1515

    
1516
	/* Add /etc/remote entry in case we need to read from the GPS with tip */
1517
	if (intval(`grep -c '^gps0' /etc/remote`) == 0) {
1518
		@file_put_contents("/etc/remote", "gps0:dv={$serialport}:br#{$gpsbaud}:pa=none:", FILE_APPEND);
1519
	}
1520

    
1521
	conf_mount_ro();
1522

    
1523
	return true;
1524
}
1525

    
1526
function system_ntp_setup_pps($serialport) {
1527
	global $config, $g;
1528

    
1529
	$pps_device = '/dev/pps0';
1530
	$serialport = '/dev/'.$serialport;
1531

    
1532
	if (!file_exists($serialport)) {
1533
		return false;
1534
	}
1535

    
1536
	conf_mount_rw();
1537
	// Create symlink that ntpd requires
1538
	unlink_if_exists($pps_device);
1539
	@symlink($serialport, $pps_device);
1540

    
1541
	conf_mount_ro();
1542

    
1543
	return true;
1544
}
1545

    
1546

    
1547
function system_ntp_configure($start_ntpd=true) {
1548
	global $config, $g;
1549

    
1550
	$driftfile = "/var/db/ntpd.drift";
1551
	$statsdir = "/var/log/ntp";
1552
	$gps_device = '/dev/gps0';
1553

    
1554
	safe_mkdir($statsdir);
1555

    
1556
	if (!is_array($config['ntpd'])) {
1557
		$config['ntpd'] = array();
1558
	}
1559

    
1560
	$ntpcfg = "# \n";
1561
	$ntpcfg .= "# pfSense ntp configuration file \n";
1562
	$ntpcfg .= "# \n\n";
1563
	$ntpcfg .= "tinker panic 0 \n";
1564

    
1565
	/* Add Orphan mode */
1566
	$ntpcfg .= "# Orphan mode stratum\n";
1567
	$ntpcfg .= 'tos orphan ';
1568
	if (!empty($config['ntpd']['orphan'])) {
1569
		$ntpcfg .= $config['ntpd']['orphan'];
1570
	} else {
1571
		$ntpcfg .= '12';
1572
	}
1573
	$ntpcfg .= "\n";
1574

    
1575
	/* Add PPS configuration */
1576
	if (is_array($config['ntpd']['pps']) && !empty($config['ntpd']['pps']['port']) &&
1577
	    file_exists('/dev/'.$config['ntpd']['pps']['port']) &&
1578
	    system_ntp_setup_pps($config['ntpd']['pps']['port'])) {
1579
		$ntpcfg .= "\n";
1580
		$ntpcfg .= "# PPS Setup\n";
1581
		$ntpcfg .= 'server 127.127.22.0';
1582
		$ntpcfg .= ' minpoll 4 maxpoll 4';
1583
		if (empty($config['ntpd']['pps']['prefer'])) { /*note: this one works backwards */
1584
			$ntpcfg .= ' prefer';
1585
		}
1586
		if (!empty($config['ntpd']['pps']['noselect'])) {
1587
			$ntpcfg .= ' noselect ';
1588
		}
1589
		$ntpcfg .= "\n";
1590
		$ntpcfg .= 'fudge 127.127.22.0';
1591
		if (!empty($config['ntpd']['pps']['fudge1'])) {
1592
			$ntpcfg .= ' time1 ';
1593
			$ntpcfg .= $config['ntpd']['pps']['fudge1'];
1594
		}
1595
		if (!empty($config['ntpd']['pps']['flag2'])) {
1596
			$ntpcfg .= ' flag2 1';
1597
		}
1598
		if (!empty($config['ntpd']['pps']['flag3'])) {
1599
			$ntpcfg .= ' flag3 1';
1600
		} else {
1601
			$ntpcfg .= ' flag3 0';
1602
		}
1603
		if (!empty($config['ntpd']['pps']['flag4'])) {
1604
			$ntpcfg .= ' flag4 1';
1605
		}
1606
		if (!empty($config['ntpd']['pps']['refid'])) {
1607
			$ntpcfg .= ' refid ';
1608
			$ntpcfg .= $config['ntpd']['pps']['refid'];
1609
		}
1610
		$ntpcfg .= "\n";
1611
	}
1612
	/* End PPS configuration */
1613

    
1614
	/* Add GPS configuration */
1615
	if (is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['port']) &&
1616
	    file_exists('/dev/'.$config['ntpd']['gps']['port']) &&
1617
	    system_ntp_setup_gps($config['ntpd']['gps']['port'])) {
1618
		$ntpcfg .= "\n";
1619
		$ntpcfg .= "# GPS Setup\n";
1620
		$ntpcfg .= 'server 127.127.20.0 mode ';
1621
		if (!empty($config['ntpd']['gps']['nmea']) || !empty($config['ntpd']['gps']['speed']) || !empty($config['ntpd']['gps']['subsec'])) {
1622
			if (!empty($config['ntpd']['gps']['nmea'])) {
1623
				$ntpmode = (int) $config['ntpd']['gps']['nmea'];
1624
			}
1625
			if (!empty($config['ntpd']['gps']['speed'])) {
1626
				$ntpmode += (int) $config['ntpd']['gps']['speed'];
1627
			}
1628
			if (!empty($config['ntpd']['gps']['subsec'])) {
1629
				$ntpmode += 128;
1630
			}
1631
			$ntpcfg .= (string) $ntpmode;
1632
		} else {
1633
			$ntpcfg .= '0';
1634
		}
1635
		$ntpcfg .= ' minpoll 4 maxpoll 4';
1636
		if (empty($config['ntpd']['gps']['prefer'])) { /*note: this one works backwards */
1637
			$ntpcfg .= ' prefer';
1638
		}
1639
		if (!empty($config['ntpd']['gps']['noselect'])) {
1640
			$ntpcfg .= ' noselect ';
1641
		}
1642
		$ntpcfg .= "\n";
1643
		$ntpcfg .= 'fudge 127.127.20.0';
1644
		if (!empty($config['ntpd']['gps']['fudge1'])) {
1645
			$ntpcfg .= ' time1 ';
1646
			$ntpcfg .= $config['ntpd']['gps']['fudge1'];
1647
		}
1648
		if (!empty($config['ntpd']['gps']['fudge2'])) {
1649
			$ntpcfg .= ' time2 ';
1650
			$ntpcfg .= $config['ntpd']['gps']['fudge2'];
1651
		}
1652
		if (!empty($config['ntpd']['gps']['flag1'])) {
1653
			$ntpcfg .= ' flag1 1';
1654
		} else {
1655
			$ntpcfg .= ' flag1 0';
1656
		}
1657
		if (!empty($config['ntpd']['gps']['flag2'])) {
1658
			$ntpcfg .= ' flag2 1';
1659
		}
1660
		if (!empty($config['ntpd']['gps']['flag3'])) {
1661
			$ntpcfg .= ' flag3 1';
1662
		} else {
1663
			$ntpcfg .= ' flag3 0';
1664
		}
1665
		if (!empty($config['ntpd']['gps']['flag4'])) {
1666
			$ntpcfg .= ' flag4 1';
1667
		}
1668
		if (!empty($config['ntpd']['gps']['refid'])) {
1669
			$ntpcfg .= ' refid ';
1670
			$ntpcfg .= $config['ntpd']['gps']['refid'];
1671
		}
1672
		if (!empty($config['ntpd']['gps']['stratum'])) {
1673
			$ntpcfg .= ' stratum ';
1674
			$ntpcfg .= $config['ntpd']['gps']['stratum'];
1675
		}
1676
		$ntpcfg .= "\n";
1677
	} elseif (is_array($config['ntpd']) && !empty($config['ntpd']['gpsport']) &&
1678
	    file_exists('/dev/'.$config['ntpd']['gpsport']) &&
1679
	    system_ntp_setup_gps($config['ntpd']['gpsport'])) {
1680
		/* This handles a 2.1 and earlier config */
1681
		$ntpcfg .= "# GPS Setup\n";
1682
		$ntpcfg .= "server 127.127.20.0 mode 0 minpoll 4 maxpoll 4 prefer\n";
1683
		$ntpcfg .= "fudge 127.127.20.0 time1 0.155 time2 0.000 flag1 1 flag2 0 flag3 1\n";
1684
		// Fall back to local clock if GPS is out of sync?
1685
		$ntpcfg .= "server 127.127.1.0\n";
1686
		$ntpcfg .= "fudge 127.127.1.0 stratum 12\n";
1687
	}
1688
	/* End GPS configuration */
1689

    
1690
	$ntpcfg .= "\n\n# Upstream Servers\n";
1691
	/* foreach through ntp servers and write out to ntpd.conf */
1692
	foreach (explode(' ', $config['system']['timeservers']) as $ts) {
1693
		$ntpcfg .= "server {$ts} iburst maxpoll 9";
1694
		if (substr_count($config['ntpd']['prefer'], $ts)) {
1695
			$ntpcfg .= ' prefer';
1696
		}
1697
		if (substr_count($config['ntpd']['noselect'], $ts)) {
1698
			$ntpcfg .= ' noselect';
1699
		}
1700
		$ntpcfg .= "\n";
1701
	}
1702
	unset($ts);
1703

    
1704
	$ntpcfg .= "\n\n";
1705
	$ntpcfg .= "disable monitor\n"; //prevent NTP reflection attack, see https://forum.pfsense.org/index.php/topic,67189.msg389132.html#msg389132
1706
	if (!empty($config['ntpd']['clockstats']) || !empty($config['ntpd']['loopstats']) || !empty($config['ntpd']['peerstats'])) {
1707
		$ntpcfg .= "enable stats\n";
1708
		$ntpcfg .= 'statistics';
1709
		if (!empty($config['ntpd']['clockstats'])) {
1710
			$ntpcfg .= ' clockstats';
1711
		}
1712
		if (!empty($config['ntpd']['loopstats'])) {
1713
			$ntpcfg .= ' loopstats';
1714
		}
1715
		if (!empty($config['ntpd']['peerstats'])) {
1716
			$ntpcfg .= ' peerstats';
1717
		}
1718
		$ntpcfg .= "\n";
1719
	}
1720
	$ntpcfg .= "statsdir {$statsdir}\n";
1721
	$ntpcfg .= 'logconfig =syncall +clockall';
1722
	if (!empty($config['ntpd']['logpeer'])) {
1723
		$ntpcfg .= ' +peerall';
1724
	}
1725
	if (!empty($config['ntpd']['logsys'])) {
1726
		$ntpcfg .= ' +sysall';
1727
	}
1728
	$ntpcfg .= "\n";
1729
	$ntpcfg .= "driftfile {$driftfile}\n";
1730
	/* Access restrictions */
1731
	$ntpcfg .= 'restrict default';
1732
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1733
		$ntpcfg .= ' kod limited';
1734
	}
1735
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1736
		$ntpcfg .= ' nomodify';
1737
	}
1738
	if (!empty($config['ntpd']['noquery'])) {
1739
		$ntpcfg .= ' noquery';
1740
	}
1741
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1742
		$ntpcfg .= ' nopeer';
1743
	}
1744
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1745
		$ntpcfg .= ' notrap';
1746
	}
1747
	if (!empty($config['ntpd']['noserve'])) {
1748
		$ntpcfg .= ' noserve';
1749
	}
1750
	$ntpcfg .= "\nrestrict -6 default";
1751
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1752
		$ntpcfg .= ' kod limited';
1753
	}
1754
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1755
		$ntpcfg .= ' nomodify';
1756
	}
1757
	if (!empty($config['ntpd']['noquery'])) {
1758
		$ntpcfg .= ' noquery';
1759
	}
1760
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1761
		$ntpcfg .= ' nopeer';
1762
	}
1763
	if (!empty($config['ntpd']['noserve'])) {
1764
		$ntpcfg .= ' noserve';
1765
	}
1766
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1767
		$ntpcfg .= ' notrap';
1768
	}
1769
	$ntpcfg .= "\n";
1770

    
1771
	/* A leapseconds file is really only useful if this clock is stratum 1 */
1772
	$ntpcfg .= "\n";
1773
	if (!empty($config['ntpd']['leapsec'])) {
1774
		$leapsec .= base64_decode($config['ntpd']['leapsec']);
1775
		file_put_contents('/var/db/leap-seconds', $leapsec);
1776
		$ntpcfg .= "leapfile /var/db/leap-seconds\n";
1777
	}
1778

    
1779

    
1780
	if (empty($config['ntpd']['interface'])) {
1781
		if (is_array($config['installedpackages']['openntpd']) && !empty($config['installedpackages']['openntpd']['config'][0]['interface'])) {
1782
			$interfaces = explode(",", $config['installedpackages']['openntpd']['config'][0]['interface']);
1783
		} else {
1784
			$interfaces = array();
1785
		}
1786
	} else {
1787
		$interfaces = explode(",", $config['ntpd']['interface']);
1788
	}
1789

    
1790
	if (is_array($interfaces) && count($interfaces)) {
1791
		$ntpcfg .= "interface ignore all\n";
1792
		foreach ($interfaces as $interface) {
1793
			if (strstr($interface, "_vip")) {
1794
				$interface = get_configured_carp_interface_list($interface);
1795
			}
1796
			if (!is_ipaddr($interface)) {
1797
				$interface = get_real_interface($interface);
1798
			}
1799
			if (!empty($interface)) {
1800
				$ntpcfg .= "interface listen {$interface}\n";
1801
			}
1802
		}
1803
	}
1804

    
1805
	/* open configuration for writing or bail */
1806
	if (!@file_put_contents("{$g['varetc_path']}/ntpd.conf", $ntpcfg)) {
1807
		log_error("Could not open {$g['varetc_path']}/ntpd.conf for writing");
1808
		return;
1809
	}
1810

    
1811
	/* At bootup we just want to write out the config. */
1812
	if (!$start_ntpd) {
1813
		return;
1814
	}
1815

    
1816
	/* if ntpd is running, kill it */
1817
	while (isvalidpid("{$g['varrun_path']}/ntpd.pid")) {
1818
		killbypid("{$g['varrun_path']}/ntpd.pid");
1819
	}
1820
	@unlink("{$g['varrun_path']}/ntpd.pid");
1821

    
1822
	/* if /var/empty does not exist, create it */
1823
	if (!is_dir("/var/empty")) {
1824
		mkdir("/var/empty", 0775, true);
1825
	}
1826

    
1827
	/* start opentpd, set time now and use /var/etc/ntpd.conf */
1828
	mwexec("/usr/local/sbin/ntpd -g -c {$g['varetc_path']}/ntpd.conf -p {$g['varrun_path']}/ntpd.pid", false, true);
1829

    
1830
	// Note that we are starting up
1831
	log_error("NTPD is starting up.");
1832
	return;
1833
}
1834

    
1835
function sync_system_time() {
1836
	global $config, $g;
1837

    
1838
	if (platform_booting()) {
1839
		echo gettext("Syncing system time before startup...");
1840
	}
1841

    
1842
	/* foreach through servers and write out to ntpd.conf */
1843
	foreach (explode(' ', $config['system']['timeservers']) as $ts) {
1844
		mwexec("/usr/local/sbin/ntpdate -s $ts");
1845
	}
1846

    
1847
	if (platform_booting()) {
1848
		echo gettext("done.") . "\n";
1849
	}
1850

    
1851
}
1852

    
1853
function system_halt() {
1854
	global $g;
1855

    
1856
	system_reboot_cleanup();
1857

    
1858
	mwexec("/usr/bin/nohup /etc/rc.halt > /dev/null 2>&1 &");
1859
}
1860

    
1861
function system_reboot() {
1862
	global $g;
1863

    
1864
	system_reboot_cleanup();
1865

    
1866
	mwexec("nohup /etc/rc.reboot > /dev/null 2>&1 &");
1867
}
1868

    
1869
function system_reboot_sync() {
1870
	global $g;
1871

    
1872
	system_reboot_cleanup();
1873

    
1874
	mwexec("/etc/rc.reboot > /dev/null 2>&1");
1875
}
1876

    
1877
function system_reboot_cleanup() {
1878
	global $config, $cpzone;
1879

    
1880
	mwexec("/usr/local/bin/beep.sh stop");
1881
	require_once("captiveportal.inc");
1882
	if (is_array($config['captiveportal'])) {
1883
		foreach ($config['captiveportal'] as $cpzone=>$cp) {
1884
			captiveportal_radius_stop_all();
1885
			captiveportal_send_server_accounting(true);
1886
		}
1887
	}
1888
	require_once("voucher.inc");
1889
	voucher_save_db_to_config();
1890
	require_once("pkg-utils.inc");
1891
	stop_packages();
1892
}
1893

    
1894
function system_do_shell_commands($early = 0) {
1895
	global $config, $g;
1896
	if (isset($config['system']['developerspew'])) {
1897
		$mt = microtime();
1898
		echo "system_do_shell_commands() being called $mt\n";
1899
	}
1900

    
1901
	if ($early) {
1902
		$cmdn = "earlyshellcmd";
1903
	} else {
1904
		$cmdn = "shellcmd";
1905
	}
1906

    
1907
	if (is_array($config['system'][$cmdn])) {
1908

    
1909
		/* *cmd is an array, loop through */
1910
		foreach ($config['system'][$cmdn] as $cmd) {
1911
			exec($cmd);
1912
		}
1913

    
1914
	} elseif ($config['system'][$cmdn] <> "") {
1915

    
1916
		/* execute single item */
1917
		exec($config['system'][$cmdn]);
1918

    
1919
	}
1920
}
1921

    
1922
function system_console_configure() {
1923
	global $config, $g;
1924
	if (isset($config['system']['developerspew'])) {
1925
		$mt = microtime();
1926
		echo "system_console_configure() being called $mt\n";
1927
	}
1928

    
1929
	if (isset($config['system']['disableconsolemenu'])) {
1930
		touch("{$g['varetc_path']}/disableconsole");
1931
	} else {
1932
		unlink_if_exists("{$g['varetc_path']}/disableconsole");
1933
	}
1934
}
1935

    
1936
function system_dmesg_save() {
1937
	global $g;
1938
	if (isset($config['system']['developerspew'])) {
1939
		$mt = microtime();
1940
		echo "system_dmesg_save() being called $mt\n";
1941
	}
1942

    
1943
	$dmesg = "";
1944
	$_gb = exec("/sbin/dmesg", $dmesg);
1945

    
1946
	/* find last copyright line (output from previous boots may be present) */
1947
	$lastcpline = 0;
1948

    
1949
	for ($i = 0; $i < count($dmesg); $i++) {
1950
		if (strstr($dmesg[$i], "Copyright (c) 1992-")) {
1951
			$lastcpline = $i;
1952
		}
1953
	}
1954

    
1955
	$fd = fopen("{$g['varlog_path']}/dmesg.boot", "w");
1956
	if (!$fd) {
1957
		printf(gettext("Error: cannot open dmesg.boot in system_dmesg_save().%s"), "\n");
1958
		return 1;
1959
	}
1960

    
1961
	for ($i = $lastcpline; $i < count($dmesg); $i++) {
1962
		fwrite($fd, $dmesg[$i] . "\n");
1963
	}
1964

    
1965
	fclose($fd);
1966
	unset($dmesg);
1967

    
1968
	return 0;
1969
}
1970

    
1971
function system_set_harddisk_standby() {
1972
	global $g, $config;
1973

    
1974
	if (isset($config['system']['developerspew'])) {
1975
		$mt = microtime();
1976
		echo "system_set_harddisk_standby() being called $mt\n";
1977
	}
1978

    
1979
	if (isset($config['system']['harddiskstandby'])) {
1980
		if (platform_booting()) {
1981
			echo gettext('Setting hard disk standby... ');
1982
		}
1983

    
1984
		$standby = $config['system']['harddiskstandby'];
1985
		// Check for a numeric value
1986
		if (is_numeric($standby)) {
1987
			// Get only suitable candidates for standby; using get_smart_drive_list()
1988
			// from utils.inc to get the list of drives.
1989
			$harddisks = get_smart_drive_list();
1990

    
1991
			// Since get_smart_drive_list() only matches ad|da|ada; lets put the check below
1992
			// just in case of some weird pfSense platform installs.
1993
			if (count($harddisks) > 0) {
1994
				// Iterate disks and run the camcontrol command for each
1995
				foreach ($harddisks as $harddisk) {
1996
					mwexec("/sbin/camcontrol standby {$harddisk} -t {$standby}");
1997
				}
1998
				if (platform_booting()) {
1999
					echo gettext("done.") . "\n";
2000
				}
2001
			} else if (platform_booting()) {
2002
				echo gettext("failed!") . "\n";
2003
			}
2004
		} else if (platform_booting()) {
2005
			echo gettext("failed!") . "\n";
2006
		}
2007
	}
2008
}
2009

    
2010
function system_setup_sysctl() {
2011
	global $config;
2012
	if (isset($config['system']['developerspew'])) {
2013
		$mt = microtime();
2014
		echo "system_setup_sysctl() being called $mt\n";
2015
	}
2016

    
2017
	activate_sysctls();
2018

    
2019
	if (isset($config['system']['sharednet'])) {
2020
		system_disable_arp_wrong_if();
2021
	}
2022
}
2023

    
2024
function system_disable_arp_wrong_if() {
2025
	global $config;
2026
	if (isset($config['system']['developerspew'])) {
2027
		$mt = microtime();
2028
		echo "system_disable_arp_wrong_if() being called $mt\n";
2029
	}
2030
	set_sysctl(array(
2031
		"net.link.ether.inet.log_arp_wrong_iface" => "0",
2032
		"net.link.ether.inet.log_arp_movements" => "0"
2033
	));
2034
}
2035

    
2036
function system_enable_arp_wrong_if() {
2037
	global $config;
2038
	if (isset($config['system']['developerspew'])) {
2039
		$mt = microtime();
2040
		echo "system_enable_arp_wrong_if() being called $mt\n";
2041
	}
2042
	set_sysctl(array(
2043
		"net.link.ether.inet.log_arp_wrong_iface" => "1",
2044
		"net.link.ether.inet.log_arp_movements" => "1"
2045
	));
2046
}
2047

    
2048
function enable_watchdog() {
2049
	global $config;
2050
	return;
2051
	$install_watchdog = false;
2052
	$supported_watchdogs = array("Geode");
2053
	$file = file_get_contents("/var/log/dmesg.boot");
2054
	foreach ($supported_watchdogs as $sd) {
2055
		if (stristr($file, "Geode")) {
2056
			$install_watchdog = true;
2057
		}
2058
	}
2059
	if ($install_watchdog == true) {
2060
		if (is_process_running("watchdogd")) {
2061
			mwexec("/usr/bin/killall watchdogd", true);
2062
		}
2063
		exec("/usr/sbin/watchdogd");
2064
	}
2065
}
2066

    
2067
function system_check_reset_button() {
2068
	global $g;
2069

    
2070
	$specplatform = system_identify_specific_platform();
2071

    
2072
	switch ($specplatform['name']) {
2073
		case 'alix':
2074
		case 'wrap':
2075
		case 'FW7541':
2076
		case 'APU':
2077
		case 'RCC-VE':
2078
		case 'RCC-DFF':
2079
			break;
2080
		default:
2081
			return 0;
2082
	}
2083

    
2084
	$retval = mwexec("/usr/local/sbin/" . $specplatform['name'] . "resetbtn");
2085

    
2086
	if ($retval == 99) {
2087
		/* user has pressed reset button for 2 seconds -
2088
		   reset to factory defaults */
2089
		echo <<<EOD
2090

    
2091
***********************************************************************
2092
* Reset button pressed - resetting configuration to factory defaults. *
2093
* The system will reboot after this completes.                        *
2094
***********************************************************************
2095

    
2096

    
2097
EOD;
2098

    
2099
		reset_factory_defaults();
2100
		system_reboot_sync();
2101
		exit(0);
2102
	}
2103

    
2104
	return 0;
2105
}
2106

    
2107
/*
2108
 * attempt to identify the specific platform (for embedded systems)
2109
 * Returns an array with two elements:
2110
 * name => platform string (e.g. 'wrap', 'alix' etc.)
2111
 * descr => human-readable description (e.g. "PC Engines WRAP")
2112
 */
2113
function system_identify_specific_platform() {
2114
	global $g;
2115

    
2116
	if ($g['platform'] == 'generic-pc') {
2117
		return array('name' => 'generic-pc', 'descr' => gettext("Generic PC"));
2118
	}
2119

    
2120
	if ($g['platform'] == 'generic-pc-cdrom') {
2121
		return array('name' => 'generic-pc-cdrom', 'descr' => gettext("Generic PC (CD-ROM)"));
2122
	}
2123

    
2124
	/* Try to guess from smbios strings */
2125
	unset($output);
2126
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output);
2127
	switch ($output[0]) {
2128
		case 'FW7541':
2129
			return (array('name' => 'FW7541', 'descr' => 'Netgate FW7541'));
2130
			break;
2131
		case 'APU':
2132
			return (array('name' => 'APU', 'descr' => 'Netgate APU'));
2133
			break;
2134
		case 'RCC-VE':
2135
			return (array('name' => 'RCC-VE', 'descr' => 'Netgate RCC-VE'));
2136
			break;
2137
		case 'DFFv2':
2138
			return (array('name' => 'RCC-DFF', 'descr' => 'Netgate RCC-DFF'));
2139
			break;
2140
		case 'SYS-5018A-FTN4':
2141
		case 'A1SAi':
2142
			return (array('name' => 'C2758', 'descr' => 'Super Micro C2758'));
2143
			break;
2144
		case 'SYS-5018D-FN4T':
2145
			return (array('name' => 'D1540-XG', 'descr' => 'Super Micro D1540-XG'));
2146
			break;
2147
	}
2148

    
2149
	/* the rest of the code only deals with 'embedded' platforms */
2150
	if ($g['platform'] != 'nanobsd') {
2151
		return array('name' => $g['platform'], 'descr' => $g['platform']);
2152
	}
2153

    
2154
	$dmesg = get_single_sysctl('hw.model');
2155

    
2156
	if (strpos($dmesg, "PC Engines WRAP") !== false) {
2157
		return array('name' => 'wrap', 'descr' => gettext('PC Engines WRAP'));
2158
	}
2159

    
2160
	if (strpos($dmesg, "PC Engines ALIX") !== false) {
2161
		return array('name' => 'alix', 'descr' => gettext('PC Engines ALIX'));
2162
	}
2163

    
2164
	if (preg_match("/Soekris net45../", $dmesg, $matches)) {
2165
		return array('name' => 'net45xx', 'descr' => $matches[0]);
2166
	}
2167

    
2168
	if (preg_match("/Soekris net48../", $dmesg, $matches)) {
2169
		return array('name' => 'net48xx', 'descr' => $matches[0]);
2170
	}
2171

    
2172
	if (preg_match("/Soekris net55../", $dmesg, $matches)) {
2173
		return array('name' => 'net55xx', 'descr' => $matches[0]);
2174
	}
2175

    
2176
	unset($dmesg);
2177

    
2178
	$dmesg_boot = system_get_dmesg_boot();
2179
	if (strpos($dmesg_boot, "PC Engines ALIX") !== false) {
2180
		return array('name' => 'alix', 'descr' => gettext('PC Engines ALIX'));
2181
	}
2182
	unset($dmesg_boot);
2183

    
2184
	/* unknown embedded platform */
2185
	return array('name' => 'embedded', 'descr' => gettext('embedded (unknown)'));
2186
}
2187

    
2188
function system_get_dmesg_boot() {
2189
	global $g;
2190

    
2191
	return file_get_contents("{$g['varlog_path']}/dmesg.boot");
2192
}
2193

    
2194
?>
(52-52/65)