Project

General

Profile

Download (67.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	system.inc
5
	part of m0n0wall (http://m0n0.ch/wall)
6

    
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

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

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
/*
33
	pfSense_BUILDER_BINARIES:	/usr/sbin/powerd	/usr/bin/killall	/sbin/route
34
	pfSense_BUILDER_BINARIES:	/bin/hostname	/bin/ls	/usr/sbin/syslogd	
35
	pfSense_BUILDER_BINARIES:	/usr/sbin/pccardd	/usr/local/sbin/lighttpd	/bin/chmod 	/bin/mkdir
36
	pfSense_BUILDER_BINARIES:	/usr/bin/tar		/usr/local/sbin/ntpd	/usr/local/sbin/ntpdate
37
	pfSense_BUILDER_BINARIES:	/usr/bin/nohup	/sbin/dmesg	/usr/local/sbin/atareinit	/sbin/kldload
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/filterdns
39
	pfSense_MODULE:	utils
40
*/
41

    
42
function activate_powerd() {
43
	global $config, $g;
44
	if ($g['platform'] == 'jail')
45
		return;
46
	if(is_process_running("powerd"))
47
		exec("/usr/bin/killall powerd");
48
	if(isset($config['system']['powerd_enable'])) {
49
		if ($g["platform"] == "nanobsd")
50
			exec("/sbin/kldload cpufreq");
51

    
52
		$ac_mode = "hadp";
53
		if (!empty($config['system']['powerd_ac_mode']))
54
			$ac_mode = $config['system']['powerd_ac_mode'];
55

    
56
		$battery_mode = "hadp";
57
		if (!empty($config['system']['powerd_battery_mode']))
58
			$battery_mode = $config['system']['powerd_battery_mode'];
59

    
60
		$normal_mode = "hadp";
61
		if (!empty($config['system']['powerd_normal_mode']))
62
			$normal_mode = $config['system']['powerd_normal_mode'];
63

    
64
		mwexec("/usr/sbin/powerd -b $battery_mode -a $ac_mode -n $normal_mode");
65
	}
66
}
67

    
68
function get_default_sysctl_value($id) {
69
	global $sysctls;
70

    
71
	if (isset($sysctls[$id]))
72
		return $sysctls[$id];
73
}
74

    
75
function get_sysctl_descr($sysctl) {
76
	unset($output);
77
	$_gb = exec("/sbin/sysctl -nd {$sysctl}", $output);
78

    
79
	return $output[0];
80
}
81

    
82
function system_get_sysctls() {
83
	global $config, $sysctls;
84

    
85
	$disp_sysctl = array();
86
	$disp_cache = array();
87
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
88
		foreach($config['sysctl']['item'] as $id => $tunable) {
89
			if ($tunable['value'] == "default")
90
				$value = get_default_sysctl_value($tunable['tunable']);
91
			else
92
				$value = $tunable['value'];
93

    
94
			$disp_sysctl[$id] = $tunable;
95
			$disp_sysctl[$id]['modified'] = true;
96
			$disp_cache[$tunable['tunable']] = 'set';
97
		}
98
	}
99

    
100
	foreach ($sysctls as $sysctl => $value) {
101
		if (isset($disp_cache[$sysctl]))
102
			continue;
103

    
104
		$disp_sysctl[$sysctl] = array('tunable' => $sysctl, 'value' => $value, 'descr' => get_sysctl_descr($sysctl));
105
	}
106
	unset($disp_cache);
107
	return $disp_sysctl;
108
}
109

    
110
function activate_sysctls() {
111
	global $config, $g, $sysctls;
112

    
113
	if ($g['platform'] == 'jail')
114
		return;
115

    
116
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
117
		foreach($config['sysctl']['item'] as $tunable) {
118
			if($tunable['value'] == "default")
119
				$value = get_default_sysctl_value($tunable['tunable']);
120
			else
121
				$value = $tunable['value'];
122

    
123
			$sysctls[$tunable['tunable']] = $value;
124
		}
125
	}
126

    
127
	set_sysctl($sysctls);
128
}
129

    
130
function system_resolvconf_generate($dynupdate = false) {
131
	global $config, $g;
132

    
133
	if(isset($config['system']['developerspew'])) {
134
		$mt = microtime();
135
		echo "system_resolvconf_generate() being called $mt\n";
136
	}
137

    
138
	$syscfg = $config['system'];
139

    
140
	if (((isset($config['dnsmasq']['enable']) && (!isset($config['dnsmasq']['port']) || $config['dnsmasq']['port'] == "53") && (empty($config['dnsmasq']['interface']) || in_array("lo0", explode(",", $config['dnsmasq']['interface']))))
141
		|| (isset($config['unbound']['enable'])) && (!isset($config['unbound']['port']) || $config['unbound']['port'] == "53") && (empty($config['unbound']['active_interface']) || in_array("lo0", explode(",", $config['unbound']['active_interface'])) || in_array("all", explode(",", $config['unbound']['active_interface']), true)))
142
		&& !isset($config['system']['dnslocalhost']))
143
		$resolvconf .= "nameserver 127.0.0.1\n";
144

    
145
	if (isset($syscfg['dnsallowoverride'])) {
146
		/* get dynamically assigned DNS servers (if any) */
147
		$ns = array_unique(get_searchdomains());
148
		foreach($ns as $searchserver) {
149
			if($searchserver)
150
				$resolvconf .= "search {$searchserver}\n";
151
		}
152
		$ns = array_unique(get_nameservers());
153
		foreach($ns as $nameserver) {
154
			if($nameserver)
155
				$resolvconf .= "nameserver $nameserver\n";
156
		}
157
	} else {
158
		$ns = array();
159
		// Do not create blank search/domain lines, it can break tools like dig.
160
		if($syscfg['domain'])
161
			$resolvconf .= "search {$syscfg['domain']}\n";
162
	}
163
	if (is_array($syscfg['dnsserver'])) {
164
		foreach ($syscfg['dnsserver'] as $sys_dnsserver) {
165
			if ($sys_dnsserver && (!in_array($sys_dnsserver, $ns))) {
166
				$resolvconf .= "nameserver $sys_dnsserver\n";
167
			}
168
		}
169
	}
170

    
171
	// Add EDNS support
172
	if (isset($config['unbound']['enable']) && isset($config['unbound']['edns']))
173
		$resolvconf .= "options edns0\n";
174

    
175
	$dnslock = lock('resolvconf', LOCK_EX);
176

    
177
	$fd = fopen("{$g['varetc_path']}/resolv.conf", "w");
178
	if (!$fd) {
179
		printf("Error: cannot open resolv.conf in system_resolvconf_generate().\n");
180
		unlock($dnslock);
181
		return 1;
182
	}
183

    
184
	fwrite($fd, $resolvconf);
185
	fclose($fd);
186

    
187
	// Prevent resolvconf(8) from rewriting our resolv.conf
188
	$fd = fopen("{$g['varetc_path']}/resolvconf.conf", "w");
189
	if (!$fd) {
190
		printf("Error: cannot open resolvconf.conf in system_resolvconf_generate().\n");
191
		return 1;
192
	}
193
	fwrite($fd, "resolv_conf=\"/dev/null\"\n");
194
	fclose($fd);
195

    
196
	if (!platform_booting()) {
197
		/* restart dhcpd (nameservers may have changed) */
198
		if (!$dynupdate)
199
			services_dhcpd_configure();
200
	}
201

    
202
	/* setup static routes for DNS servers. */
203
	for ($dnscounter=1; $dnscounter<5; $dnscounter++) {
204
		/* setup static routes for dns servers */
205
		$dnsgw = "dns{$dnscounter}gw";
206
		if (isset($config['system'][$dnsgw])) {
207
			$gwname = $config['system'][$dnsgw];
208
			if (($gwname <> "") && ($gwname <> "none")) {
209
				$gatewayip = lookup_gateway_ip_by_name($gwname);
210
				if (is_ipaddrv4($gatewayip)) {
211
					/* dns server array starts at 0 */
212
					$dnscountermo = $dnscounter - 1;
213
					mwexec("/sbin/route change -host " . $syscfg['dnsserver'][$dnscountermo] . " {$gatewayip}");
214
					if (isset($config['system']['route-debug'])) {
215
						$mt = microtime();
216
						log_error("ROUTING debug: $mt - route change -host {$syscfg['dnsserver'][$dnscountermo]} $gatewayip ");
217
					}
218
				}
219
				if (is_ipaddrv6($gatewayip)) {
220
					/* dns server array starts at 0 */
221
					$dnscountermo = $dnscounter - 1;
222
					mwexec("/sbin/route change -host -inet6 " . $syscfg['dnsserver'][$dnscountermo] . " {$gatewayip}");
223
					if (isset($config['system']['route-debug'])) {
224
						$mt = microtime();
225
						log_error("ROUTING debug: $mt - route change -host -inet6 {$syscfg['dnsserver'][$dnscountermo]} $gatewayip ");
226
					}					
227
				}
228
			}
229
		}
230
	}
231

    
232
	unlock($dnslock);
233

    
234
	return 0;
235
}
236

    
237
function get_searchdomains() {
238
	global $config, $g;
239

    
240
	$master_list = array();
241
	
242
	// Read in dhclient nameservers
243
	$search_list = glob("/var/etc/searchdomain_*");
244
	if (is_array($search_list)) {
245
		foreach($search_list as $fdns) {
246
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
247
			if (!is_array($contents))
248
				continue;
249
			foreach ($contents as $dns) {
250
				if(is_hostname($dns)) 
251
					$master_list[] = $dns;
252
			}
253
		}
254
	}
255

    
256
	return $master_list;
257
}
258

    
259
function get_nameservers() {
260
	global $config, $g;
261
	$master_list = array();
262
	
263
	// Read in dhclient nameservers
264
	$dns_lists = glob("/var/etc/nameserver_*");
265
	if (is_array($dns_lists)) {
266
		foreach($dns_lists as $fdns) {
267
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
268
			if (!is_array($contents))
269
				continue;
270
			foreach ($contents as $dns) {
271
				if(is_ipaddr($dns)) 
272
					$master_list[] = $dns;
273
			}
274
		}
275
	}
276

    
277
	// Read in any extra nameservers
278
	if(file_exists("/var/etc/nameservers.conf")) {
279
		$dns_s = file("/var/etc/nameservers.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
280
		if(is_array($dns_s)) {
281
			foreach($dns_s as $dns)
282
				if (is_ipaddr($dns))
283
					$master_list[] = $dns;
284
		}
285
	}
286

    
287
	return $master_list;
288
}
289

    
290
function system_hosts_generate() {
291
	global $config, $g;
292
	if (isset($config['system']['developerspew'])) {
293
		$mt = microtime();
294
		echo "system_hosts_generate() being called $mt\n";
295
	}
296

    
297
	$syscfg = $config['system'];
298
	if (isset($config['unbound']) && isset($config['unbound']['enable']))
299
		$dnsmasqcfg = $config['unbound'];
300
	else
301
		$dnsmasqcfg = $config['dnsmasq'];
302

    
303
	$hosts =  "127.0.0.1	localhost localhost.{$syscfg['domain']}\n";
304
	$hosts .= "::1		localhost localhost.{$syscfg['domain']}\n";
305
	$lhosts = "";
306
	$dhosts = "";
307

    
308
	if ($config['interfaces']['lan']) {
309
		$cfgip = get_interface_ip("lan");
310
		if (is_ipaddr($cfgip))
311
			$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
312
		$cfgipv6 = get_interface_ipv6("lan");
313
		if (is_ipaddrv6($cfgipv6))
314
			$hosts .= "{$cfgipv6}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
315
	} else {
316
		$sysiflist = get_configured_interface_list();
317
		$hosts_if_found = false;
318
		foreach ($sysiflist as $sysif) {
319
			if (!interface_has_gateway($sysif)) {
320
				$cfgip = get_interface_ip($sysif);
321
				if (is_ipaddr($cfgip)) {
322
					$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
323
					$hosts_if_found = true;
324
				}
325
				$cfgipv6 = get_interface_ipv6($sysif);
326
				if (is_ipaddrv6($cfgipv6)) {
327
					$hosts .= "{$cfgipv6}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
328
					$hosts_if_found = true;
329
				}
330
				if ($hosts_if_found == true)
331
					break;
332
			}
333
		}
334
	}
335

    
336
	if (isset($dnsmasqcfg['enable'])) {
337
		if (!is_array($dnsmasqcfg['hosts']))
338
			$dnsmasqcfg['hosts'] = array();
339

    
340
		foreach ($dnsmasqcfg['hosts'] as $host) {
341
			if ($host['host'] || $host['host'] == "0")
342
				$lhosts .= "{$host['ip']}	{$host['host']}.{$host['domain']} {$host['host']}\n";
343
			else
344
				$lhosts .= "{$host['ip']}	{$host['domain']}\n";
345
			if (!is_array($host['aliases']) || !is_array($host['aliases']['item']))
346
				continue;
347
			foreach ($host['aliases']['item'] as $alias) {
348
				if ($alias['host'] || $alias['host'] == "0")
349
					$lhosts .= "{$host['ip']}	{$alias['host']}.{$alias['domain']} {$alias['host']}\n";
350
				else
351
					$lhosts .= "{$host['ip']}	{$alias['domain']}\n";
352
			}
353
		}
354
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpd'])) {
355
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf)
356
				if(is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable']))
357
						foreach ($dhcpifconf['staticmap'] as $host)
358
							if ($host['ipaddr'] && $host['hostname'] && $host['domain'])
359
								$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
360
							else if ($host['ipaddr'] && $host['hostname'] && $dhcpifconf['domain'])
361
								$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
362
							else if ($host['ipaddr'] && $host['hostname'])
363
								$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
364
		}
365
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpdv6'])) {
366
			foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf)
367
				if(is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable']))
368
						foreach ($dhcpifconf['staticmap'] as $host)
369
							if ($host['ipaddrv6'] && $host['hostname'] && $host['domain'])
370
								$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
371
							else if ($host['ipaddrv6'] && $host['hostname'] && $dhcpifconf['domain'])
372
								$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
373
							else if ($host['ipaddrv6'] && $host['hostname'])
374
								$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
375
		}
376

    
377
		if (isset($dnsmasqcfg['dhcpfirst']))
378
			$hosts .= $dhosts . $lhosts;
379
		else
380
			$hosts .= $lhosts . $dhosts;
381
	}
382

    
383
	/*
384
	 * Do not remove this because dhcpleases monitors with kqueue it needs to be 
385
	 * killed before writing to hosts files.
386
	 */
387
	if (file_exists("{$g['varrun_path']}/dhcpleases.pid")) {
388
		sigkillbypid("{$g['varrun_path']}/dhcpleases.pid", "TERM");
389
		@unlink("{$g['varrun_path']}/dhcpleases.pid");
390
	}
391
	$fd = fopen("{$g['varetc_path']}/hosts", "w");
392
	if (!$fd) {
393
		log_error("Error: cannot open hosts file in system_hosts_generate().\n");
394
		return 1;
395
	}
396
	fwrite($fd, $hosts);
397
	fclose($fd);
398

    
399
	if (isset($config['unbound']['enable'])) {
400
		require_once("unbound.inc");
401
		unbound_hosts_generate();
402
	}
403

    
404
	return 0;
405
}
406

    
407
function system_dhcpleases_configure() {
408
	global $config, $g;
409
	
410
	if ($g['platform'] == 'jail')
411
		return;
412
	/* Start the monitoring process for dynamic dhcpclients. */
413
	if ((isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcp'])) 
414
		|| (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcp']))) {
415
		/* Make sure we do not error out */
416
		mwexec("/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db");
417
		if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"))
418
			@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
419

    
420
		if (isset($config['unbound']['enable'])) {
421
			$dns_pid = "unbound.pid";
422
			$unbound_conf = "-u {$g['unbound_chroot_path']}/dhcpleases_entries.conf";
423
		} else {
424
			$dns_pid = "dnsmasq.pid";
425
			$unbound_conf = "";
426
		}
427

    
428
		$pidfile = "{$g['varrun_path']}/dhcpleases.pid";
429
		if (isvalidpid($pidfile)) {
430
			/* Make sure dhcpleases is using correct unbound or dnsmasq */
431
			$_gb = exec("/bin/pgrep -F {$pidfile} -f {$dns_pid}", $output, $retval);
432
			if (intval($retval) == 0) {
433
				sigkillbypid($pidfile, "HUP");
434
				return;
435
			} else
436
				sigkillbypid($pidfile, "TERM");
437
		}
438

    
439
		/* To ensure we do not start multiple instances of dhcpleases, perform some clean-up first. */
440
		if (is_process_running("dhcpleases"))
441
			sigkillbyname('dhcpleases', "TERM");
442
		@unlink($pidfile);
443
		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");
444
	} else {
445
		sigkillbypid($pidfile, "TERM");
446
		@unlink($pidfile);
447
	}
448
}
449

    
450
function system_hostname_configure() {
451
	global $config, $g;
452
	if(isset($config['system']['developerspew'])) {
453
		$mt = microtime();
454
		echo "system_hostname_configure() being called $mt\n";
455
	}
456

    
457
	$syscfg = $config['system'];
458

    
459
	/* set hostname */
460
	$status = mwexec("/bin/hostname " .
461
		escapeshellarg("{$syscfg['hostname']}.{$syscfg['domain']}"));
462

    
463
    /* Setup host GUID ID.  This is used by ZFS. */
464
	mwexec("/etc/rc.d/hostid start");
465

    
466
	return $status;
467
}
468

    
469
function system_routing_configure($interface = "") {
470
	global $config, $g;
471
	if ($g['platform'] == 'jail')
472
		return;
473
	if(isset($config['system']['developerspew'])) {
474
		$mt = microtime();
475
		echo "system_routing_configure() being called $mt\n";
476
	}
477

    
478
	$gatewayip = "";
479
	$interfacegw = "";
480
	$gatewayipv6 = "";
481
	$interfacegwv6 = "";
482
	$foundgw = false;
483
	$foundgwv6 = false;
484
	/* tack on all the hard defined gateways as well */
485
	if (is_array($config['gateways']['gateway_item'])) {
486
		array_map('unlink', glob("{$g['tmp_path']}/*_defaultgw{,v6}", GLOB_BRACE));
487
		foreach	($config['gateways']['gateway_item'] as $gateway) {
488
			if (isset($gateway['defaultgw'])) {
489
				if ($foundgw == false && ($gateway['ipprotocol'] != "inet6" && (is_ipaddrv4($gateway['gateway']) || $gateway['gateway'] == "dynamic"))) {
490
					if(strpos($gateway['gateway'], ":"))
491
						continue;
492
					if ($gateway['gateway'] == "dynamic")
493
						$gateway['gateway'] = get_interface_gateway($gateway['interface']);
494
					$gatewayip = $gateway['gateway'];
495
					$interfacegw = $gateway['interface'];
496
					if (!empty($gateway['interface'])) {
497
						$defaultif = get_real_interface($gateway['interface']);
498
						if ($defaultif)
499
							@file_put_contents("{$g['tmp_path']}/{$defaultif}_defaultgw", $gateway['gateway']);
500
					}
501
					$foundgw = true;
502
				} else if ($foundgwv6 == false && ($gateway['ipprotocol'] == "inet6" && (is_ipaddrv6($gateway['gateway']) || $gateway['gateway'] == "dynamic"))) {
503
					if ($gateway['gateway'] == "dynamic")
504
						$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
505
					$gatewayipv6 = $gateway['gateway'];
506
					$interfacegwv6 = $gateway['interface'];
507
					if (!empty($gateway['interface'])) {
508
						$defaultifv6 = get_real_interface($gateway['interface']);
509
						if ($defaultifv6)
510
							@file_put_contents("{$g['tmp_path']}/{$defaultifv6}_defaultgwv6", $gateway['gateway']);
511
					}
512
					$foundgwv6 = true;
513
				}
514
			}
515
			if ($foundgw === true && $foundgwv6 === true)
516
				break;
517
		}
518
	}
519
	if ($foundgw == false) {
520
		$defaultif = get_real_interface("wan");
521
		$interfacegw = "wan";
522
		$gatewayip = get_interface_gateway("wan");
523
		@file_put_contents("{$g['tmp_path']}/{$defaultif}_defaultgw", $gatewayip);
524
	}	
525
	if ($foundgwv6 == false) {
526
		$defaultifv6 = get_real_interface("wan");
527
		$interfacegwv6 = "wan";
528
		$gatewayipv6 = get_interface_gateway_v6("wan");
529
		@file_put_contents("{$g['tmp_path']}/{$defaultifv6}_defaultgwv6", $gatewayipv6);
530
	}
531
	$dont_add_route = false;
532
	/* if OLSRD is enabled, allow WAN to house DHCP. */
533
	if (is_array($config['installedpackages']['olsrd'])) {
534
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd) {
535
			if(($olsrd['enabledyngw'] == "on") && ($olsrd['enable'] == "on")) {
536
				$dont_add_route = true;
537
				log_error(sprintf(gettext("Not adding default route because OLSR dynamic gateway is enabled.")));
538
				break;
539
			}
540
		}
541
	}
542

    
543
	if ($dont_add_route == false ) {
544
		if (!empty($interface) && $interface != $interfacegw)
545
			;
546
		else if (is_ipaddrv4($gatewayip)) {
547
			log_error("ROUTING: setting default route to $gatewayip");
548
			mwexec("/sbin/route change -inet default " . escapeshellarg($gatewayip));
549
		}
550

    
551
		if (!empty($interface) && $interface != $interfacegwv6)
552
			;
553
		else if (is_ipaddrv6($gatewayipv6)) {
554
			$ifscope = "";
555
			if (is_linklocal($gatewayipv6) && !strpos($gatewayipv6, '%'))
556
				$ifscope = "%{$defaultifv6}";
557
			log_error("ROUTING: setting IPv6 default route to {$gatewayipv6}{$ifscope}");
558
			mwexec("/sbin/route change -inet6 default " . escapeshellarg("{$gatewayipv6}{$ifscope}"));
559
		}
560
	}
561

    
562
	system_staticroutes_configure($interface, false);
563

    
564
	return 0;
565
}
566

    
567
function system_staticroutes_configure($interface = "", $update_dns = false) {
568
	global $config, $g, $aliastable;
569

    
570
	$filterdns_list = array();
571

    
572
	$static_routes = get_staticroutes(false, true);
573
	if (count($static_routes)) {
574
		$gateways_arr = return_gateways_array(false, true);
575

    
576
		foreach ($static_routes as $rtent) {
577
			if (empty($gateways_arr[$rtent['gateway']])) {
578
				log_error(sprintf(gettext("Static Routes: Gateway IP could not be found for %s"), $rtent['network']));
579
				continue;
580
			}
581
			$gateway = $gateways_arr[$rtent['gateway']];
582
			if (!empty($interface) && $interface != $gateway['friendlyiface'])
583
				continue;
584

    
585
			$gatewayip = $gateway['gateway'];
586
			$interfacegw = $gateway['interface'];
587

    
588
			$blackhole = "";
589
			if (!strcasecmp("Null", substr($rtent['gateway'], 0, 3)))
590
				$blackhole = "-blackhole";
591

    
592
			if (!is_fqdn($rtent['network']) && !is_subnet($rtent['network']))
593
				continue;
594

    
595
			$dnscache = array();
596
			if ($update_dns === true) {
597
				if (is_subnet($rtent['network']))
598
					continue;
599
				$dnscache = explode("\n", trim(compare_hostname_to_dnscache($rtent['network'])));
600
				if (empty($dnscache))
601
					continue;
602
			}
603

    
604
			if (is_subnet($rtent['network']))
605
				$ips = array($rtent['network']);
606
			else {
607
				if (!isset($rtent['disabled']))
608
					$filterdns_list[] = $rtent['network'];
609
				$ips = add_hostname_to_watch($rtent['network']);
610
			}
611

    
612
			foreach ($dnscache as $ip) {
613
				if (in_array($ip, $ips))
614
					continue;
615
				mwexec("/sbin/route delete " . escapeshellarg($ip), true);
616
				if (isset($config['system']['route-debug'])) {
617
					$mt = microtime();
618
					log_error("ROUTING debug: $mt - route delete $ip ");
619
				}
620
			}
621

    
622
			if (isset($rtent['disabled'])) {
623
				/* XXX: This can break things by deleting routes that shouldn't be deleted - OpenVPN, dynamic routing scenarios, etc. redmine #3709 */
624
				foreach ($ips as $ip) {
625
					mwexec("/sbin/route delete " . escapeshellarg($ip), true);
626
					if (isset($config['system']['route-debug'])) {
627
						$mt = microtime();
628
						log_error("ROUTING debug: $mt - route delete $ip ");
629
					}
630
				}
631
				continue;
632
			}
633

    
634
			foreach ($ips as $ip) {
635
				if (is_ipaddrv4($ip))
636
					$ip .= "/32";
637
				// do NOT do the same check here on v6, is_ipaddrv6 returns true when including the CIDR mask. doing so breaks v6 routes
638
					
639
				$inet = (is_subnetv6($ip) ? "-inet6" : "-inet");
640

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

    
643
				if (is_subnet($ip))
644
					if (is_ipaddr($gatewayip)) {
645
						mwexec($cmd . escapeshellarg($gatewayip));
646
						if (isset($config['system']['route-debug'])) {
647
							$mt = microtime();
648
							log_error("ROUTING debug: $mt - $cmd $gatewayip");
649
						}
650
					} else if (!empty($interfacegw)) {
651
						mwexec($cmd . "-iface " . escapeshellarg($interfacegw));
652
						if (isset($config['system']['route-debug'])) {
653
							$mt = microtime();
654
							log_error("ROUTING debug: $mt - $cmd -iface $interfacegw ");
655
						}
656
					}
657
			}
658
		}
659
		unset($gateways_arr);
660
	}
661
	unset($static_routes);
662

    
663
	if ($update_dns === false) {
664
		if (count($filterdns_list)) {
665
			$interval = 60;
666
			$hostnames = "";
667
			array_unique($filterdns_list);
668
			foreach ($filterdns_list as $hostname)
669
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload routedns\"'\n";
670
			file_put_contents("{$g['varetc_path']}/filterdns-route.hosts", $hostnames);
671
			unset($hostnames);
672

    
673
			if (isvalidpid("{$g['varrun_path']}/filterdns-route.pid"))
674
				sigkillbypid("{$g['varrun_path']}/filterdns-route.pid", "HUP");
675
			else
676
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-route.pid -i {$interval} -c {$g['varetc_path']}/filterdns-route.hosts -d 1");
677
		} else {
678
			killbypid("{$g['varrun_path']}/filterdns-route.pid");
679
			@unlink("{$g['varrun_path']}/filterdns-route.pid");
680
		}
681
	}
682
	unset($filterdns_list);
683

    
684
	return 0;
685
}
686

    
687
function system_routing_enable() {
688
	global $config, $g;
689
	if(isset($config['system']['developerspew'])) {
690
		$mt = microtime();
691
		echo "system_routing_enable() being called $mt\n";
692
	}
693

    
694
	set_sysctl(array(
695
		"net.inet.ip.forwarding" => "1",
696
		"net.inet6.ip6.forwarding" => "1"
697
	));
698

    
699
	return;
700
}
701

    
702
function system_syslogd_fixup_server($server) {
703
	/* If it's an IPv6 IP alone, encase it in brackets */
704
	if (is_ipaddrv6($server))
705
		return "[$server]";
706
	else
707
		return $server;
708
}
709

    
710
function system_syslogd_get_remote_servers($syslogcfg, $facility = "*.*") {
711
	// Rather than repeatedly use the same code, use this function to build a list of remote servers.
712
	$facility .= " ".
713
	$remote_servers = "";
714
	$pad_to  = 56;
715
	$padding = ceil(($pad_to - strlen($facility))/8)+1;
716
	if($syslogcfg['remoteserver'])
717
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver']) . "\n";
718
	if($syslogcfg['remoteserver2'])
719
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver2']) . "\n";
720
	if($syslogcfg['remoteserver3'])
721
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver3']) . "\n";
722
	return $remote_servers;
723
}
724

    
725
function system_syslogd_start() {
726
	global $config, $g;
727
	if(isset($config['system']['developerspew'])) {
728
		$mt = microtime();
729
		echo "system_syslogd_start() being called $mt\n";
730
	}
731

    
732
	mwexec("/etc/rc.d/hostid start");
733

    
734
	$syslogcfg = $config['syslog'];
735

    
736
	if (platform_booting())
737
		echo gettext("Starting syslog...");
738

    
739
	if (is_process_running("fifolog_writer"))
740
		mwexec('/bin/pkill fifolog_writer');
741

    
742
	// Which logging type are we using this week??
743
	if (isset($config['system']['disablesyslogclog'])) {
744
		$log_directive = "";
745
		$log_create_directive = "/usr/bin/touch ";
746
		$log_size = "";
747
	} else if (isset($config['system']['usefifolog'])) {
748
		$log_directive = "|/usr/sbin/fifolog_writer ";
749
		$log_size = isset($config['syslog']['logfilesize']) ? $config['syslog']['logfilesize'] : "10240";
750
		$log_create_directive = "/usr/sbin/fifolog_create -s ";
751
	} else { // Defaults to CLOG
752
		$log_directive = "%";
753
		$log_size = isset($config['syslog']['logfilesize']) ? $config['syslog']['logfilesize'] : "10240";
754
		$log_create_directive = "/usr/local/sbin/clog -i -s ";
755
	}
756

    
757
	$syslogd_extra = "";
758
	if (isset($syslogcfg)) {
759
		$separatelogfacilities = array('ntp','ntpd','ntpdate','charon','ipsec_starter','openvpn','pptps','poes','l2tps','relayd','hostapd','dnsmasq','filterdns','unbound','dhcpd','dhcrelay','dhclient','dhcp6c','apinger','radvd','routed','olsrd','zebra','ospfd','bgpd','miniupnpd','filterlog');
760
		$syslogconf = "";
761
		if($config['installedpackages']['package']) {
762
			foreach($config['installedpackages']['package'] as $package) {
763
				if($package['logging']) {
764
					array_push($separatelogfacilities, $package['logging']['facilityname']);
765
					if (!is_file($g['varlog_path'].'/'.$package['logging']['logfilename']))
766
						mwexec("{$log_create_directive} {$log_size} {$g['varlog_path']}/{$package['logging']['logfilename']}");
767
					$syslogconf .= "!{$package['logging']['facilityname']}\n*.*\t\t\t\t\t\t {$log_directive}{$g['varlog_path']}/{$package['logging']['logfilename']}\n";
768
				}
769
			}
770
		}
771
		$facilitylist = implode(',', array_unique($separatelogfacilities));
772
		$syslogconf .= "!radvd,routed,olsrd,zebra,ospfd,bgpd,miniupnpd\n";
773
		if (!isset($syslogcfg['disablelocallogging']))
774
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/routing.log\n";
775

    
776
		$syslogconf .= "!ntp,ntpd,ntpdate\n";
777
		if (!isset($syslogcfg['disablelocallogging'])) 
778
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ntpd.log\n";
779

    
780
		$syslogconf .= "!ppp\n";
781
		if (!isset($syslogcfg['disablelocallogging'])) 
782
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ppp.log\n";
783

    
784
		$syslogconf .= "!pptps\n";
785
		if (!isset($syslogcfg['disablelocallogging'])) 
786
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/pptps.log\n";
787

    
788
		$syslogconf .= "!poes\n";
789
		if (!isset($syslogcfg['disablelocallogging'])) 
790
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/poes.log\n";
791

    
792
		$syslogconf .= "!l2tps\n";
793
		if (!isset($syslogcfg['disablelocallogging'])) 
794
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/l2tps.log\n";
795

    
796
		$syslogconf .= "!charon,ipsec_starter\n";
797
		if (!isset($syslogcfg['disablelocallogging'])) 
798
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/ipsec.log\n";
799
		if (isset($syslogcfg['vpn']))
800
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
801

    
802
		$syslogconf .= "!openvpn\n";
803
		if (!isset($syslogcfg['disablelocallogging'])) 
804
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/openvpn.log\n";
805
		if (isset($syslogcfg['vpn']))
806
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
807

    
808
		$syslogconf .= "!apinger\n";
809
		if (!isset($syslogcfg['disablelocallogging']))
810
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/gateways.log\n";
811
		if (isset($syslogcfg['apinger']))
812
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
813

    
814
		$syslogconf .= "!dnsmasq,filterdns,unbound\n";
815
		if (!isset($syslogcfg['disablelocallogging']))
816
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/resolver.log\n";
817

    
818
		$syslogconf .= "!dhcpd,dhcrelay,dhclient,dhcp6c\n";
819
		if (!isset($syslogcfg['disablelocallogging']))
820
			$syslogconf .= "*.*								{$log_directive}{$g['varlog_path']}/dhcpd.log\n";
821
		if (isset($syslogcfg['dhcp']))
822
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
823

    
824
		$syslogconf .= "!relayd\n";
825
		if (!isset($syslogcfg['disablelocallogging']))
826
			$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/relayd.log\n";
827
		if (isset($syslogcfg['relayd']))
828
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
829

    
830
		$syslogconf .= "!hostapd\n";
831
		if (!isset($syslogcfg['disablelocallogging']))
832
			$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/wireless.log\n";
833
		if (isset($syslogcfg['hostapd']))
834
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
835

    
836
		$syslogconf .= "!filterlog\n";
837
		$syslogconf .= "*.* 								{$log_directive}{$g['varlog_path']}/filter.log\n";
838
		if (isset($syslogcfg['filter']))
839
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
840

    
841
		$syslogconf .= "!-{$facilitylist}\n";
842
		if (!isset($syslogcfg['disablelocallogging'])) 
843
			$syslogconf .= <<<EOD
844
local3.*							{$log_directive}{$g['varlog_path']}/vpn.log
845
local4.*							{$log_directive}{$g['varlog_path']}/portalauth.log
846
local7.*							{$log_directive}{$g['varlog_path']}/dhcpd.log
847
*.notice;kern.debug;lpr.info;mail.crit;daemon.none;		{$log_directive}{$g['varlog_path']}/system.log
848
news.err;local0.none;local3.none;local4.none;			{$log_directive}{$g['varlog_path']}/system.log
849
local7.none							{$log_directive}{$g['varlog_path']}/system.log
850
security.*							{$log_directive}{$g['varlog_path']}/system.log
851
auth.info;authpriv.info;daemon.info				{$log_directive}{$g['varlog_path']}/system.log
852
auth.info;authpriv.info 					|exec /usr/local/sbin/sshlockout_pf 15
853
*.emerg								*
854

    
855
EOD;
856
		if (isset($syslogcfg['vpn']))
857
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local3.*");
858
		if (isset($syslogcfg['portalauth']))
859
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local4.*");
860
		if (isset($syslogcfg['dhcp']))
861
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local7.*");
862
		if (isset($syslogcfg['system'])) {
863
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.notice;kern.debug;lpr.info;mail.crit;");
864
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "news.err;local0.none;local3.none;local7.none");
865
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "security.*");
866
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "auth.info;authpriv.info;daemon.info");
867
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.emerg");
868
		}
869
		if (isset($syslogcfg['logall'])) {
870
			// Make everything mean everything, including facilities excluded above.
871
			$syslogconf .= "!*\n";
872
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
873
		}
874

    
875
		if (isset($syslogcfg['zmqserver'])) {
876
				$syslogconf .= <<<EOD
877
*.*								^{$syslogcfg['zmqserver']}
878

    
879
EOD;
880
		}
881
		/* write syslog.conf */		
882
		if (!@file_put_contents("{$g['varetc_path']}/syslog.conf", $syslogconf)) {
883
			printf(gettext("Error: cannot open syslog.conf in system_syslogd_start().%s"), "\n");
884
			unset($syslogconf);
885
			return 1;
886
		}
887
		unset($syslogconf);
888

    
889
		// Ensure that the log directory exists
890
		if (!is_dir("{$g['dhcpd_chroot_path']}/var/run"))
891
			exec("/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/run");
892

    
893
		$sourceip = "";
894
		if (!empty($syslogcfg['sourceip'])) {
895
			if ($syslogcfg['ipproto'] == "ipv6") {
896
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ipv6($syslogcfg['sourceip']);
897
				if (!is_ipaddr($ifaddr))
898
					$ifaddr = get_interface_ip($syslogcfg['sourceip']);
899
			} else {
900
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ip($syslogcfg['sourceip']);
901
				if (!is_ipaddr($ifaddr))
902
					$ifaddr = get_interface_ipv6($syslogcfg['sourceip']);
903
			}
904
			if (is_ipaddr($ifaddr)) {
905
				$sourceip = "-b {$ifaddr}";
906
			}
907
		}
908

    
909
		$syslogd_extra = "-f {$g['varetc_path']}/syslog.conf {$sourceip}";
910
	}
911

    
912
	if (isvalidpid("{$g['varrun_path']}/syslog.pid")) {
913
		sigkillbypid("{$g['varrun_path']}/syslog.pid", "TERM");
914
		usleep(100000); // syslogd often doesn't respond to a TERM quickly enough for the starting of syslogd below to be successful
915
	}
916
	
917
	if (isvalidpid("{$g['varrun_path']}/syslog.pid")) {
918
		// if it still hasn't responded to the TERM, KILL it. 
919
		sigkillbypid("{$g['varrun_path']}/syslog.pid", "KILL");
920
		usleep(100000); 
921
	}
922

    
923
	
924
	$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}");
925

    
926
	if (platform_booting())
927
		echo gettext("done.") . "\n";
928

    
929
	return $retval;
930
}
931

    
932
function system_webgui_create_certificate() {
933
	global $config, $g;
934

    
935
	if (!is_array($config['ca']))
936
		$config['ca'] = array();
937
	$a_ca =& $config['ca'];
938
	if (!is_array($config['cert']))
939
		$config['cert'] = array();
940
	$a_cert =& $config['cert'];
941
	log_error("Creating SSL Certificate for this host");
942

    
943
	$cert = array();
944
	$cert['refid'] = uniqid();
945
	$cert['descr'] = gettext("webConfigurator default ({$cert['refid']})");
946

    
947
	$dn = array(
948
		'countryName' => "US",
949
		'stateOrProvinceName' => "State",
950
		'localityName' => "Locality",
951
		'organizationName' => "{$g['product_name']} webConfigurator Self-Signed Certificate",
952
		'emailAddress' => "admin@{$config['system']['hostname']}.{$config['system']['domain']}",
953
		'commonName' => "{$config['system']['hostname']}-{$cert['refid']}");
954
	$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warnings directly to a page screwing menu tab */
955
	if (!cert_create($cert, null, 2048, 2000, $dn, "self-signed", "sha256")){
956
		while($ssl_err = openssl_error_string()){
957
			log_error("Error creating WebGUI Certificate: openssl library returns: " . $ssl_err);
958
		}
959
		error_reporting($old_err_level);
960
		return null;
961
	}
962
	error_reporting($old_err_level);
963

    
964
	$a_cert[] = $cert;
965
	$config['system']['webgui']['ssl-certref'] = $cert['refid'];
966
	write_config(gettext("Generated new self-signed HTTPS certificate ({$cert['refid']})"));
967
	return $cert;
968
}
969

    
970
function system_webgui_start() {
971
	global $config, $g;
972

    
973
	if (platform_booting())
974
		echo gettext("Starting webConfigurator...");
975

    
976
	chdir($g['www_path']);
977

    
978
	/* defaults */
979
	$portarg = "80";
980
	$crt = "";
981
	$key = "";
982
	$ca = "";
983

    
984
	/* non-standard port? */
985
	if (isset($config['system']['webgui']['port']) && $config['system']['webgui']['port'] <> "")
986
		$portarg = "{$config['system']['webgui']['port']}";
987

    
988
	if ($config['system']['webgui']['protocol'] == "https") {
989
		// Ensure that we have a webConfigurator CERT
990
		$cert =& lookup_cert($config['system']['webgui']['ssl-certref']);
991
		if(!is_array($cert) || !$cert['crt'] || !$cert['prv'])
992
			$cert = system_webgui_create_certificate();
993
		$crt = base64_decode($cert['crt']);
994
		$key = base64_decode($cert['prv']);
995

    
996
		if(!$config['system']['webgui']['port'])
997
			$portarg = "443";
998
		$ca  = ca_chain($cert);
999
	}
1000

    
1001
	/* generate lighttpd configuration */
1002
	system_generate_lighty_config("{$g['varetc_path']}/lighty-webConfigurator.conf",
1003
		$crt, $key, $ca, "lighty-webConfigurator.pid", $portarg, "/usr/local/www/",
1004
		"cert.pem", "ca.pem");
1005

    
1006
	/* kill any running lighttpd */
1007
	killbypid("{$g['varrun_path']}/lighty-webConfigurator.pid");
1008

    
1009
	sleep(1);
1010

    
1011
	@unlink("{$g['varrun_path']}/lighty-webConfigurator.pid");
1012

    
1013
	/* attempt to start lighthttpd */
1014
	$res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-webConfigurator.conf");
1015

    
1016
	if (platform_booting()) {
1017
		if ($res == 0)
1018
			echo gettext("done.") . "\n";
1019
		else
1020
			echo gettext("failed!") . "\n";
1021
	}
1022

    
1023
	return $res;
1024
}
1025

    
1026
function system_generate_lighty_config($filename,
1027
	$cert,
1028
	$key,
1029
	$ca,
1030
	$pid_file,
1031
	$port = 80,
1032
	$document_root = "/usr/local/www/",
1033
	$cert_location = "cert.pem",
1034
	$ca_location = "ca.pem",
1035
	$captive_portal = false) {
1036

    
1037
	global $config, $g;
1038

    
1039
	if(!is_dir("{$g['tmp_path']}/lighttpdcompress"))
1040
		mkdir("{$g['tmp_path']}/lighttpdcompress");
1041

    
1042
	if(isset($config['system']['developerspew'])) {
1043
		$mt = microtime();
1044
		echo "system_generate_lighty_config() being called $mt\n";
1045
	}
1046

    
1047
	if ($captive_portal !== false)  {
1048
		$captiveportal = ",\"mod_rewrite\",\"mod_evasive\"";
1049
		$captive_portal_rewrite = "url.rewrite-once = ( \"(.*captiveportal.*)\" => \"$1\", \"(.*)\" => \"/index.php?zone={$captive_portal}&redirurl=$1\" )\n";
1050

    
1051
		$maxprocperip = $config['captiveportal'][$captive_portal]['maxprocperip'];
1052
		if (empty($maxprocperip))
1053
			$maxprocperip = 10;
1054
		$captive_portal_mod_evasive = "evasive.max-conns-per-ip = {$maxprocperip}";
1055

    
1056
		$server_upload_dirs = "server.upload-dirs = ( \"{$g['tmp_path']}/captiveportal/\" )\n";
1057
		if(!is_dir("{$g['tmp_path']}/captiveportal"))
1058
			@mkdir("{$g['tmp_path']}/captiveportal", 0555);
1059
		$server_max_request_size = "server.max-request-size    = 384";
1060
		$cgi_config = "";
1061
	} else {
1062
		$captiveportal = ",\"mod_cgi\"";
1063
		$captive_portal_rewrite = "";
1064
		$captive_portal_mod_evasive = "";
1065
		$server_upload_dirs = "server.upload-dirs = ( \"{$g['upload_path']}/\", \"{$g['tmp_path']}/\", \"/var/\" )\n";
1066
		$server_max_request_size = "server.max-request-size    = 2097152";
1067
		$cgi_config = "cgi.assign                 = ( \".cgi\" => \"\" )";
1068
	}
1069
	
1070
	if (empty($port))
1071
		$lighty_port = "80";
1072
	else
1073
		$lighty_port = $port;
1074

    
1075
	$memory = get_memory();
1076
	$realmem = $memory[1];
1077

    
1078
	// Determine web GUI process settings and take into account low memory systems
1079
	if ($realmem < 255)
1080
		$max_procs = 1;
1081
	else
1082
		$max_procs = ($config['system']['webgui']['max_procs']) ? $config['system']['webgui']['max_procs'] : 2;
1083

    
1084
	// Ramp up captive portal max procs, assuming each PHP process can consume up to 64MB RAM 
1085
	if ($captive_portal !== false)  {
1086
		if ($realmem > 135 and $realmem < 256) {
1087
			$max_procs += 1; // 2 worker processes
1088
		} else if ($realmem > 255 and $realmem < 513) {
1089
			$max_procs += 2; // 3 worker processes
1090
		} else if ($realmem > 512) {
1091
			$max_procs += 4; // 6 worker processes
1092
		}
1093
		if ($max_procs > 1)
1094
			$max_php_children = intval($max_procs/2);
1095
		else
1096
			$max_php_children = 1;
1097

    
1098
	} else {
1099
		if ($realmem < 78)
1100
			$max_php_children = 0;
1101
		else
1102
			$max_php_children = 1;
1103
	}
1104

    
1105
	if(!isset($config['syslog']['nologlighttpd'])) {
1106
		$lighty_use_syslog = <<<EOD
1107
## where to send error-messages to
1108
server.errorlog-use-syslog="enable"
1109
EOD;
1110
	}
1111

    
1112

    
1113
	if ($captive_portal !== false) {
1114
		$fast_cgi_path = "{$g['tmp_path']}/php-fastcgi-{$captive_portal}.socket";
1115
		$fastcgi_config = <<<EOD
1116
#### fastcgi module
1117
## read fastcgi.txt for more info
1118
fastcgi.server = ( ".php" =>
1119
	( "localhost" =>
1120
		(
1121
			"socket" => "{$fast_cgi_path}",
1122
			"max-procs" => {$max_procs},
1123
			"bin-environment" => (
1124
				"PHP_FCGI_CHILDREN" => "{$max_php_children}",
1125
				"PHP_FCGI_MAX_REQUESTS" => "500"
1126
			),
1127
			"bin-path" => "/usr/local/bin/php"
1128
		)
1129
	)
1130
)
1131

    
1132
EOD;
1133
	} else {
1134
		$fast_cgi_path = "{$g['varrun_path']}/php-fpm.socket";
1135
		$fastcgi_config = <<<EOD
1136
#### fastcgi module
1137
## read fastcgi.txt for more info
1138
fastcgi.server = ( ".php" =>
1139
	( "localhost" =>
1140
		(
1141
			"socket" => "{$fast_cgi_path}",
1142
			"broken-scriptfilename" => "enable"
1143
		)
1144
	)
1145
)
1146

    
1147
EOD;
1148
	}
1149

    
1150

    
1151
	$lighty_config = <<<EOD
1152
#
1153
# lighttpd configuration file
1154
#
1155
# use a it as base for lighttpd 1.0.0 and above
1156
#
1157
############ Options you really have to take care of ####################
1158

    
1159
## FreeBSD!
1160
server.event-handler	= "freebsd-kqueue"
1161
server.network-backend 	= "writev"
1162
#server.use-ipv6 = "enable"
1163

    
1164
## modules to load
1165
server.modules              =   ( "mod_access", "mod_expire", "mod_compress", "mod_redirect",
1166
	{$captiveportal}, "mod_fastcgi"
1167
)
1168

    
1169
server.max-keep-alive-requests = 15
1170
server.max-keep-alive-idle = 30
1171

    
1172
## a static document-root, for virtual-hosting take look at the
1173
## server.virtual-* options
1174
server.document-root        = "{$document_root}"
1175
{$captive_portal_rewrite}
1176

    
1177
# Maximum idle time with nothing being written (php downloading)
1178
server.max-write-idle = 999
1179

    
1180
{$lighty_use_syslog}
1181

    
1182
# files to check for if .../ is requested
1183
server.indexfiles           = ( "index.php", "index.html",
1184
                                "index.htm", "default.htm" )
1185

    
1186
# mimetype mapping
1187
mimetype.assign             = (
1188
  ".pdf"          =>      "application/pdf",
1189
  ".sig"          =>      "application/pgp-signature",
1190
  ".spl"          =>      "application/futuresplash",
1191
  ".class"        =>      "application/octet-stream",
1192
  ".ps"           =>      "application/postscript",
1193
  ".torrent"      =>      "application/x-bittorrent",
1194
  ".dvi"          =>      "application/x-dvi",
1195
  ".gz"           =>      "application/x-gzip",
1196
  ".pac"          =>      "application/x-ns-proxy-autoconfig",
1197
  ".swf"          =>      "application/x-shockwave-flash",
1198
  ".tar.gz"       =>      "application/x-tgz",
1199
  ".tgz"          =>      "application/x-tgz",
1200
  ".tar"          =>      "application/x-tar",
1201
  ".zip"          =>      "application/zip",
1202
  ".mp3"          =>      "audio/mpeg",
1203
  ".m3u"          =>      "audio/x-mpegurl",
1204
  ".wma"          =>      "audio/x-ms-wma",
1205
  ".wax"          =>      "audio/x-ms-wax",
1206
  ".ogg"          =>      "audio/x-wav",
1207
  ".wav"          =>      "audio/x-wav",
1208
  ".gif"          =>      "image/gif",
1209
  ".jpg"          =>      "image/jpeg",
1210
  ".jpeg"         =>      "image/jpeg",
1211
  ".png"          =>      "image/png",
1212
  ".xbm"          =>      "image/x-xbitmap",
1213
  ".xpm"          =>      "image/x-xpixmap",
1214
  ".xwd"          =>      "image/x-xwindowdump",
1215
  ".css"          =>      "text/css",
1216
  ".html"         =>      "text/html",
1217
  ".htm"          =>      "text/html",
1218
  ".js"           =>      "text/javascript",
1219
  ".asc"          =>      "text/plain",
1220
  ".c"            =>      "text/plain",
1221
  ".conf"         =>      "text/plain",
1222
  ".text"         =>      "text/plain",
1223
  ".txt"          =>      "text/plain",
1224
  ".dtd"          =>      "text/xml",
1225
  ".xml"          =>      "text/xml",
1226
  ".mpeg"         =>      "video/mpeg",
1227
  ".mpg"          =>      "video/mpeg",
1228
  ".mov"          =>      "video/quicktime",
1229
  ".qt"           =>      "video/quicktime",
1230
  ".avi"          =>      "video/x-msvideo",
1231
  ".asf"          =>      "video/x-ms-asf",
1232
  ".asx"          =>      "video/x-ms-asf",
1233
  ".wmv"          =>      "video/x-ms-wmv",
1234
  ".bz2"          =>      "application/x-bzip",
1235
  ".tbz"          =>      "application/x-bzip-compressed-tar",
1236
  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
1237
 )
1238

    
1239
# Use the "Content-Type" extended attribute to obtain mime type if possible
1240
#mimetypes.use-xattr        = "enable"
1241

    
1242
## deny access the file-extensions
1243
#
1244
# ~    is for backupfiles from vi, emacs, joe, ...
1245
# .inc is often used for code includes which should in general not be part
1246
#      of the document-root
1247
url.access-deny             = ( "~", ".inc" )
1248

    
1249

    
1250
######### Options that are good to be but not necessary to be changed #######
1251

    
1252
## bind to port (default: 80)
1253

    
1254
EOD;
1255

    
1256
	$lighty_config .= "server.bind  = \"0.0.0.0\"\n";
1257
	$lighty_config .= "server.port  = {$lighty_port}\n";
1258
	$lighty_config .= "\$SERVER[\"socket\"]  == \"0.0.0.0:{$lighty_port}\" { }\n";
1259
	$lighty_config .= "\$SERVER[\"socket\"]  == \"[::]:{$lighty_port}\" { \n";
1260
	if($cert <> "" and $key <> "") {
1261
		$lighty_config .= "\n";
1262
		$lighty_config .= "## ssl configuration\n";
1263
		$lighty_config .= "ssl.engine = \"enable\"\n";
1264
		$lighty_config .= "ssl.pemfile = \"{$g['varetc_path']}/{$cert_location}\"\n\n";
1265
		if($ca <> "")
1266
			$lighty_config .= "ssl.ca-file = \"{$g['varetc_path']}/{$ca_location}\"\n\n";
1267
	}
1268
	$lighty_config .= " }\n";
1269

    
1270

    
1271
	$lighty_config .= <<<EOD
1272

    
1273
## error-handler for status 404
1274
#server.error-handler-404   = "/error-handler.html"
1275
#server.error-handler-404   = "/error-handler.php"
1276

    
1277
## to help the rc.scripts
1278
server.pid-file            = "{$g['varrun_path']}/{$pid_file}"
1279

    
1280
## virtual directory listings
1281
server.dir-listing         = "disable"
1282

    
1283
## enable debugging
1284
debug.log-request-header   = "disable"
1285
debug.log-response-header  = "disable"
1286
debug.log-request-handling = "disable"
1287
debug.log-file-not-found   = "disable"
1288

    
1289
# gzip compression
1290
compress.cache-dir = "{$g['tmp_path']}/lighttpdcompress/"
1291
compress.filetype  = ("text/plain","text/css", "text/xml", "text/javascript" )
1292

    
1293
{$server_upload_dirs}
1294

    
1295
{$server_max_request_size}
1296

    
1297
{$fastcgi_config}
1298

    
1299
{$cgi_config}
1300

    
1301
{$captive_portal_mod_evasive}
1302

    
1303
expire.url = (
1304
				"" => "access 50 hours",	
1305
        )
1306

    
1307
EOD;
1308

    
1309
	$cert = str_replace("\r", "", $cert);
1310
	$key = str_replace("\r", "", $key);
1311
	$ca = str_replace("\r", "", $ca);
1312

    
1313
	$cert = str_replace("\n\n", "\n", $cert);
1314
	$key = str_replace("\n\n", "\n", $key);
1315
	$ca = str_replace("\n\n", "\n", $ca);
1316

    
1317
	if($cert <> "" and $key <> "") {
1318
		$fd = fopen("{$g['varetc_path']}/{$cert_location}", "w");
1319
		if (!$fd) {
1320
			printf(gettext("Error: cannot open cert.pem in system_webgui_start().%s"), "\n");
1321
			return 1;
1322
		}
1323
		chmod("{$g['varetc_path']}/{$cert_location}", 0600);
1324
		fwrite($fd, $cert);
1325
		fwrite($fd, "\n");
1326
		fwrite($fd, $key);
1327
		fclose($fd);
1328
		if(!(empty($ca) || (strlen(trim($ca)) == 0))) {
1329
			$fd = fopen("{$g['varetc_path']}/{$ca_location}", "w");
1330
			if (!$fd) {
1331
				printf(gettext("Error: cannot open ca.pem in system_webgui_start().%s"), "\n");
1332
				return 1;
1333
			}
1334
			chmod("{$g['varetc_path']}/{$ca_location}", 0600);
1335
			fwrite($fd, $ca);
1336
			fclose($fd);
1337
		}
1338
		$lighty_config .= "\n";
1339
		$lighty_config .= "## " . gettext("ssl configuration") . "\n";
1340
		$lighty_config .= "ssl.engine = \"enable\"\n";
1341
		$lighty_config .= "ssl.pemfile = \"{$g['varetc_path']}/{$cert_location}\"\n\n";
1342

    
1343
		// SSLv2/3 is deprecated, force use of TLS
1344
		$lighty_config .= "ssl.use-sslv2 = \"disable\"\n";
1345
		$lighty_config .= "ssl.use-sslv3 = \"disable\"\n";
1346

    
1347
		// where ssl.cipher-list is set, this is automatically enabled, but set it explicitly anyway.
1348
		$lighty_config .= "ssl.honor-cipher-order = \"enable\"\n";
1349

    
1350
		$lighty_config .= "ssl.cipher-list = \"AES128+EECDH:AES256+EECDH:AES128+EDH:AES256+EDH:AES128-SHA:AES256-SHA:!aNULL:!eNULL:!DSS\"\n";
1351

    
1352
		if(!(empty($ca) || (strlen(trim($ca)) == 0)))
1353
			$lighty_config .= "ssl.ca-file = \"{$g['varetc_path']}/{$ca_location}\"\n\n";
1354
	}
1355

    
1356
	// Add HTTP to HTTPS redirect	
1357
	if ($captive_portal === false && $config['system']['webgui']['protocol'] == "https" && !isset($config['system']['webgui']['disablehttpredirect'])) {
1358
		if($lighty_port != "443") 
1359
			$redirectport = ":{$lighty_port}";
1360
		$lighty_config .= <<<EOD
1361
\$SERVER["socket"] == ":80" {
1362
	\$HTTP["host"] =~ "(.*)" {
1363
		url.redirect = ( "^/(.*)" => "https://%1{$redirectport}/$1" )
1364
	}
1365
}
1366
\$SERVER["socket"] == "[::]:80" {
1367
	\$HTTP["host"] =~ "(.*)" {
1368
		url.redirect = ( "^/(.*)" => "https://%1{$redirectport}/$1" )
1369
	}
1370
}
1371
EOD;
1372
	}
1373

    
1374
	$fd = fopen("{$filename}", "w");
1375
	if (!$fd) {
1376
		printf(gettext("Error: cannot open %s in system_generate_lighty_config().%s"), $filename, "\n");
1377
		return 1;
1378
	}
1379
	fwrite($fd, $lighty_config);
1380
	fclose($fd);
1381

    
1382
	return 0;
1383

    
1384
}
1385

    
1386
function system_timezone_configure() {
1387
	global $config, $g;
1388
	if(isset($config['system']['developerspew'])) {
1389
		$mt = microtime();
1390
		echo "system_timezone_configure() being called $mt\n";
1391
	}
1392

    
1393
	$syscfg = $config['system'];
1394

    
1395
	if (platform_booting())
1396
		echo gettext("Setting timezone...");
1397

    
1398
	/* extract appropriate timezone file */
1399
	$timezone = $syscfg['timezone'];
1400
	if ($timezone) {
1401
		exec('/usr/bin/tar -tvzf /usr/share/zoneinfo.tgz', $tzs);
1402
		foreach ($tzs as $tz) {
1403
			if (preg_match(",{$timezone}$,", $tz))
1404
				break;
1405
			if (preg_match(",{$timezone} link to *(.*)$,", $tz, $matches)) {
1406
				$timezone = $matches[1];
1407
				break;
1408
			}
1409
		}
1410
	} else
1411
		$timezone = "Etc/UTC";
1412

    
1413
	conf_mount_rw();
1414

    
1415
	exec("LANG=C /usr/bin/tar xzfO /usr/share/zoneinfo.tgz " .
1416
		escapeshellarg($timezone) . " > /etc/localtime");
1417

    
1418
	mwexec("sync");
1419
	conf_mount_ro();
1420

    
1421
	if (platform_booting())
1422
		echo gettext("done.") . "\n";
1423
}
1424

    
1425
function system_ntp_setup_gps($serialport) {
1426
	global $config, $g;
1427
	$gps_device = '/dev/gps0';
1428
	$serialport = '/dev/'.$serialport;
1429

    
1430
	if (!file_exists($serialport))
1431
		return false;
1432

    
1433
	conf_mount_rw();
1434
	// Create symlink that ntpd requires
1435
	unlink_if_exists($gps_device);
1436
	@symlink($serialport, $gps_device);
1437

    
1438
	$gpsbaud = '4800';
1439
	if (is_array($config['ntpd']) && is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['speed'])) {
1440
		switch ($config['ntpd']['gps']['speed']) {
1441
			case '16':
1442
				$gpsbaud = '9600';
1443
				break;
1444
			case '32':
1445
				$gpsbaud = '19200';
1446
				break;
1447
			case '48':
1448
				$gpsbaud = '38400';
1449
				break;
1450
			case '64':
1451
				$gpsbaud = '57600';
1452
				break;
1453
			case '80':
1454
				$gpsbaud = '115200';
1455
				break;
1456
		}
1457
	}
1458

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

    
1462
	/* Send the following to the GPS port to initialize the GPS */
1463
	if (is_array($config['ntpd']) && is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['type'])) {
1464
		$gps_init = base64_decode($config['ntpd']['gps']['initcmd']);
1465
	}else{
1466
		$gps_init = base64_decode('JFBVQlgsNDAsR1NWLDAsMCwwLDAqNTkNCiRQVUJYLDQwLEdMTCwwLDAsMCwwKjVDDQokUFVCWCw0MCxaREEsMCwwLDAsMCo0NA0KJFBVQlgsNDAsVlRHLDAsMCwwLDAqNUUNCiRQVUJYLDQwLEdTViwwLDAsMCwwKjU5DQokUFVCWCw0MCxHU0EsMCwwLDAsMCo0RQ0KJFBVQlgsNDAsR0dBLDAsMCwwLDANCiRQVUJYLDQwLFRYVCwwLDAsMCwwDQokUFVCWCw0MCxSTUMsMCwwLDAsMCo0Ng0KJFBVQlgsNDEsMSwwMDA3LDAwMDMsNDgwMCwwDQokUFVCWCw0MCxaREEsMSwxLDEsMQ==');
1467
	}
1468

    
1469
	/* XXX: Why not file_put_contents to the device */
1470
	@file_put_contents('/tmp/gps.init', $gps_init);
1471
	mwexec("cat /tmp/gps.init > {$serialport}");
1472

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

    
1478
	conf_mount_ro();
1479

    
1480
	return true;
1481
}
1482

    
1483
function system_ntp_setup_pps($serialport) {
1484
	global $config, $g;
1485

    
1486
	$pps_device = '/dev/pps0';
1487
	$serialport = '/dev/'.$serialport;
1488

    
1489
	if (!file_exists($serialport))
1490
		return false;
1491

    
1492
	conf_mount_rw();
1493
	// Create symlink that ntpd requires
1494
	unlink_if_exists($pps_device);
1495
	@symlink($serialport, $pps_device);
1496

    
1497
	conf_mount_ro();
1498

    
1499
	return true;
1500
}
1501

    
1502

    
1503
function system_ntp_configure($start_ntpd=true) {
1504
	global $config, $g;
1505

    
1506
	$driftfile = "/var/db/ntpd.drift";
1507
	$statsdir = "/var/log/ntp";
1508
	$gps_device = '/dev/gps0';
1509

    
1510
	if ($g['platform'] == 'jail')
1511
		return;
1512

    
1513
	safe_mkdir($statsdir);
1514

    
1515
	if (!is_array($config['ntpd']))
1516
		$config['ntpd'] = array();
1517

    
1518
	$ntpcfg = "# \n";
1519
	$ntpcfg .= "# pfSense ntp configuration file \n";
1520
	$ntpcfg .= "# \n\n";
1521
	$ntpcfg .= "tinker panic 0 \n";
1522

    
1523
	/* Add Orphan mode */
1524
	$ntpcfg .= "# Orphan mode stratum\n";
1525
	$ntpcfg .= 'tos orphan ';
1526
	if (!empty($config['ntpd']['orphan'])) {
1527
		$ntpcfg .= $config['ntpd']['orphan'];
1528
	}else{
1529
		$ntpcfg .= '12';
1530
	}
1531
	$ntpcfg .= "\n";
1532

    
1533
	/* Add PPS configuration */
1534
	if (is_array($config['ntpd']['pps']) && !empty($config['ntpd']['pps']['port'])
1535
		&& file_exists('/dev/'.$config['ntpd']['pps']['port'])
1536
		&& system_ntp_setup_pps($config['ntpd']['pps']['port'])) {
1537
		$ntpcfg .= "\n";
1538
		$ntpcfg .= "# PPS Setup\n";
1539
		$ntpcfg .= 'server 127.127.22.0';
1540
		$ntpcfg .= ' minpoll 4 maxpoll 4';
1541
		if (empty($config['ntpd']['pps']['prefer'])) { /*note: this one works backwards */
1542
			$ntpcfg .= ' prefer'; 
1543
		}
1544
		if (!empty($config['ntpd']['pps']['noselect'])) {
1545
			$ntpcfg .= ' noselect ';
1546
		}
1547
		$ntpcfg .= "\n";
1548
		$ntpcfg .= 'fudge 127.127.22.0';
1549
		if (!empty($config['ntpd']['pps']['fudge1'])) {
1550
			$ntpcfg .= ' time1 ';
1551
			$ntpcfg .= $config['ntpd']['pps']['fudge1'];
1552
		}
1553
		if (!empty($config['ntpd']['pps']['flag2'])) {
1554
			$ntpcfg .= ' flag2 1';
1555
		}
1556
		if (!empty($config['ntpd']['pps']['flag3'])) {
1557
			$ntpcfg .= ' flag3 1';
1558
		}else{
1559
			$ntpcfg .= ' flag3 0';
1560
		}
1561
		if (!empty($config['ntpd']['pps']['flag4'])) {
1562
			$ntpcfg .= ' flag4 1';
1563
		}
1564
		if (!empty($config['ntpd']['pps']['refid'])) {
1565
			$ntpcfg .= ' refid ';
1566
			$ntpcfg .= $config['ntpd']['pps']['refid'];
1567
		}
1568
		$ntpcfg .= "\n";
1569
	}
1570
	/* End PPS configuration */
1571

    
1572
	/* Add GPS configuration */
1573
	if (is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['port'])
1574
		&& file_exists('/dev/'.$config['ntpd']['gps']['port'])
1575
		&& system_ntp_setup_gps($config['ntpd']['gps']['port'])) {
1576
		$ntpcfg .= "\n";
1577
		$ntpcfg .= "# GPS Setup\n";
1578
		$ntpcfg .= 'server 127.127.20.0 mode ';
1579
		if (!empty($config['ntpd']['gps']['nmea']) || !empty($config['ntpd']['gps']['speed']) || !empty($config['ntpd']['gps']['subsec'])) {
1580
			if (!empty($config['ntpd']['gps']['nmea'])) {
1581
				$ntpmode = (int) $config['ntpd']['gps']['nmea'];
1582
			}
1583
			if (!empty($config['ntpd']['gps']['speed'])) {
1584
				$ntpmode += (int) $config['ntpd']['gps']['speed'];
1585
			}
1586
			if (!empty($config['ntpd']['gps']['subsec'])) {
1587
				$ntpmode += 128;
1588
			}
1589
			$ntpcfg .= (string) $ntpmode;
1590
		}else{
1591
			$ntpcfg .= '0';
1592
		}
1593
		$ntpcfg .= ' minpoll 4 maxpoll 4';
1594
		if (empty($config['ntpd']['gps']['prefer'])) { /*note: this one works backwards */
1595
			$ntpcfg .= ' prefer'; 
1596
		}
1597
		if (!empty($config['ntpd']['gps']['noselect'])) {
1598
			$ntpcfg .= ' noselect ';
1599
		}
1600
		$ntpcfg .= "\n";
1601
		$ntpcfg .= 'fudge 127.127.20.0';
1602
		if (!empty($config['ntpd']['gps']['fudge1'])) {
1603
			$ntpcfg .= ' time1 ';
1604
			$ntpcfg .= $config['ntpd']['gps']['fudge1'];
1605
		}
1606
		if (!empty($config['ntpd']['gps']['fudge2'])) {
1607
			$ntpcfg .= ' time2 ';
1608
			$ntpcfg .= $config['ntpd']['gps']['fudge2'];
1609
		}
1610
		if (!empty($config['ntpd']['gps']['flag1'])) {
1611
			$ntpcfg .= ' flag1 1';
1612
		}else{
1613
			$ntpcfg .= ' flag1 0';
1614
		}
1615
		if (!empty($config['ntpd']['gps']['flag2'])) {
1616
			$ntpcfg .= ' flag2 1';
1617
		}
1618
		if (!empty($config['ntpd']['gps']['flag3'])) {
1619
			$ntpcfg .= ' flag3 1';
1620
		}else{
1621
			$ntpcfg .= ' flag3 0';
1622
		}
1623
		if (!empty($config['ntpd']['gps']['flag4'])) {
1624
			$ntpcfg .= ' flag4 1';
1625
		}
1626
		if (!empty($config['ntpd']['gps']['refid'])) {
1627
			$ntpcfg .= ' refid ';
1628
			$ntpcfg .= $config['ntpd']['gps']['refid'];
1629
		}
1630
		$ntpcfg .= "\n";
1631
	}elseif (is_array($config['ntpd']) && !empty($config['ntpd']['gpsport'])
1632
		&& file_exists('/dev/'.$config['ntpd']['gpsport'])
1633
		&& system_ntp_setup_gps($config['ntpd']['gpsport'])) {
1634
		/* This handles a 2.1 and earlier config */
1635
		$ntpcfg .= "# GPS Setup\n";
1636
		$ntpcfg .= "server 127.127.20.0 mode 0 minpoll 4 maxpoll 4 prefer\n";
1637
		$ntpcfg .= "fudge 127.127.20.0 time1 0.155 time2 0.000 flag1 1 flag2 0 flag3 1\n";
1638
		// Fall back to local clock if GPS is out of sync?
1639
		$ntpcfg .= "server 127.127.1.0\n";
1640
		$ntpcfg .= "fudge 127.127.1.0 stratum 12\n";
1641
	}
1642
	/* End GPS configuration */
1643
	
1644
	$ntpcfg .= "\n\n# Upstream Servers\n";
1645
	/* foreach through ntp servers and write out to ntpd.conf */
1646
	foreach (explode(' ', $config['system']['timeservers']) as $ts) {
1647
		$ntpcfg .= "server {$ts} iburst maxpoll 9";
1648
		if (substr_count($config['ntpd']['prefer'], $ts)) $ntpcfg .= ' prefer';
1649
		if (substr_count($config['ntpd']['noselect'], $ts)) $ntpcfg .= ' noselect';
1650
		$ntpcfg .= "\n";
1651
	}
1652
	unset($ts);
1653

    
1654
	$ntpcfg .= "\n\n";
1655
	$ntpcfg .= "disable monitor\n"; //prevent NTP reflection attack, see https://forum.pfsense.org/index.php/topic,67189.msg389132.html#msg389132
1656
	if (!empty($config['ntpd']['clockstats']) || !empty($config['ntpd']['loopstats']) || !empty($config['ntpd']['peerstats'])) {
1657
		$ntpcfg .= "enable stats\n";
1658
		$ntpcfg .= 'statistics';
1659
		if (!empty($config['ntpd']['clockstats'])) {
1660
			$ntpcfg .= ' clockstats';
1661
		}
1662
		if (!empty($config['ntpd']['loopstats'])) {
1663
			$ntpcfg .= ' loopstats';
1664
		}
1665
		if (!empty($config['ntpd']['peerstats'])) {
1666
			$ntpcfg .= ' peerstats';
1667
		}
1668
		$ntpcfg .= "\n";
1669
	}
1670
	$ntpcfg .= "statsdir {$statsdir}\n";
1671
	$ntpcfg .= 'logconfig =syncall +clockall';
1672
	if (!empty($config['ntpd']['logpeer'])) {
1673
		$ntpcfg .= ' +peerall';
1674
	}
1675
	if (!empty($config['ntpd']['logsys'])) {
1676
		$ntpcfg .= ' +sysall';
1677
	}
1678
	$ntpcfg .= "\n";
1679
	$ntpcfg .= "driftfile {$driftfile}\n";
1680
	/* Access restrictions */
1681
	$ntpcfg .= 'restrict default';
1682
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1683
		$ntpcfg .= ' kod limited'; 
1684
	}
1685
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1686
		$ntpcfg .= ' nomodify'; 
1687
	}
1688
	if (!empty($config['ntpd']['noquery'])) {
1689
		$ntpcfg .= ' noquery';
1690
	}
1691
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1692
		$ntpcfg .= ' nopeer'; 
1693
	}
1694
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1695
		$ntpcfg .= ' notrap'; 
1696
	}
1697
	if (!empty($config['ntpd']['noserve'])) {
1698
		$ntpcfg .= ' noserve';
1699
	}
1700
	$ntpcfg .= "\nrestrict -6 default";
1701
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1702
		$ntpcfg .= ' kod limited'; 
1703
	}
1704
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1705
		$ntpcfg .= ' nomodify'; 
1706
	}
1707
	if (!empty($config['ntpd']['noquery'])) {
1708
		$ntpcfg .= ' noquery';
1709
	}
1710
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1711
		$ntpcfg .= ' nopeer'; 
1712
	}
1713
	if (!empty($config['ntpd']['noserve'])) {
1714
		$ntpcfg .= ' noserve';
1715
	}
1716
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1717
		$ntpcfg .= ' notrap'; 
1718
	}
1719
	$ntpcfg .= "\n";
1720

    
1721
	/* A leapseconds file is really only useful if this clock is stratum 1 */
1722
	$ntpcfg .= "\n";
1723
	if (!empty($config['ntpd']['leapsec'])) {
1724
		$leapsec .= base64_decode($config['ntpd']['leapsec']);
1725
		file_put_contents('/var/db/leap-seconds', $leapsec);
1726
		$ntpcfg .= "leapfile /var/db/leap-seconds\n";
1727
	}
1728
	
1729

    
1730
	if (empty($config['ntpd']['interface'])) {
1731
		if (is_array($config['installedpackages']['openntpd']) && !empty($config['installedpackages']['openntpd']['config'][0]['interface']))
1732
			$interfaces = explode(",", $config['installedpackages']['openntpd']['config'][0]['interface']);
1733
		else
1734
			$interfaces = array();
1735
	} else
1736
		$interfaces = explode(",", $config['ntpd']['interface']);
1737

    
1738
	if (is_array($interfaces) && count($interfaces)) {
1739
		$ntpcfg .= "interface ignore all\n";
1740
		foreach ($interfaces as $interface) {
1741
			if (strstr($interface, "_vip")) {
1742
				$interface = get_configured_carp_interface_list($interface);
1743
			}
1744
			if (!is_ipaddr($interface)) {
1745
				$interface = get_real_interface($interface);
1746
			}
1747
			if (!empty($interface))
1748
				$ntpcfg .= "interface listen {$interface}\n";
1749
		}
1750
	}
1751

    
1752
	/* open configuration for writing or bail */
1753
	if (!@file_put_contents("{$g['varetc_path']}/ntpd.conf", $ntpcfg)) {
1754
		log_error("Could not open {$g['varetc_path']}/ntpd.conf for writing");
1755
		return;
1756
	}
1757

    
1758
	/* At bootup we just want to write out the config. */
1759
	if (!$start_ntpd)
1760
		return;
1761

    
1762
	/* if ntpd is running, kill it */
1763
	while (isvalidpid("{$g['varrun_path']}/ntpd.pid")) {
1764
		killbypid("{$g['varrun_path']}/ntpd.pid");
1765
	}
1766
	@unlink("{$g['varrun_path']}/ntpd.pid");
1767

    
1768
	/* if /var/empty does not exist, create it */
1769
	if(!is_dir("/var/empty"))
1770
		mkdir("/var/empty", 0775, true);
1771

    
1772
	/* start opentpd, set time now and use /var/etc/ntpd.conf */
1773
	mwexec("/usr/local/sbin/ntpd -g -c {$g['varetc_path']}/ntpd.conf -p {$g['varrun_path']}/ntpd.pid", false, true);
1774
	
1775
	// Note that we are starting up
1776
	log_error("NTPD is starting up.");
1777
	return;
1778
}
1779

    
1780
function sync_system_time() {
1781
	global $config, $g;
1782

    
1783
	if (platform_booting())
1784
		echo gettext("Syncing system time before startup...");
1785

    
1786
	/* foreach through servers and write out to ntpd.conf */
1787
	foreach (explode(' ', $config['system']['timeservers']) as $ts) {
1788
		mwexec("/usr/local/sbin/ntpdate -s $ts");
1789
	}
1790
	
1791
	if (platform_booting())
1792
		echo gettext("done.") . "\n";
1793
	
1794
}
1795

    
1796
function system_halt() {
1797
	global $g;
1798

    
1799
	system_reboot_cleanup();
1800

    
1801
	mwexec("/usr/bin/nohup /etc/rc.halt > /dev/null 2>&1 &");
1802
}
1803

    
1804
function system_reboot() {
1805
	global $g;
1806

    
1807
	system_reboot_cleanup();
1808

    
1809
	mwexec("nohup /etc/rc.reboot > /dev/null 2>&1 &");
1810
}
1811

    
1812
function system_reboot_sync() {
1813
	global $g;
1814

    
1815
	system_reboot_cleanup();
1816

    
1817
	mwexec("/etc/rc.reboot > /dev/null 2>&1");
1818
}
1819

    
1820
function system_reboot_cleanup() {
1821
	global $config, $cpzone;
1822

    
1823
	mwexec("/usr/local/bin/beep.sh stop");
1824
	require_once("captiveportal.inc");
1825
	if (is_array($config['captiveportal'])) {
1826
		foreach ($config['captiveportal'] as $cpzone=>$cp) {
1827
			captiveportal_radius_stop_all();
1828
			captiveportal_send_server_accounting(true);
1829
		}
1830
	}
1831
	require_once("voucher.inc");
1832
	voucher_save_db_to_config();
1833
	require_once("pkg-utils.inc");
1834
	stop_packages();
1835
}
1836

    
1837
function system_do_shell_commands($early = 0) {
1838
	global $config, $g;
1839
	if(isset($config['system']['developerspew'])) {
1840
		$mt = microtime();
1841
		echo "system_do_shell_commands() being called $mt\n";
1842
	}
1843

    
1844
	if ($early)
1845
		$cmdn = "earlyshellcmd";
1846
	else
1847
		$cmdn = "shellcmd";
1848

    
1849
	if (is_array($config['system'][$cmdn])) {
1850

    
1851
		/* *cmd is an array, loop through */
1852
		foreach ($config['system'][$cmdn] as $cmd) {
1853
			exec($cmd);
1854
		}
1855

    
1856
	} elseif($config['system'][$cmdn] <> "") {
1857

    
1858
		/* execute single item */
1859
		exec($config['system'][$cmdn]);
1860

    
1861
	}
1862
}
1863

    
1864
function system_console_configure() {
1865
	global $config, $g;
1866
	if(isset($config['system']['developerspew'])) {
1867
		$mt = microtime();
1868
		echo "system_console_configure() being called $mt\n";
1869
	}
1870

    
1871
	if (isset($config['system']['disableconsolemenu'])) {
1872
		touch("{$g['varetc_path']}/disableconsole");
1873
	} else {
1874
		unlink_if_exists("{$g['varetc_path']}/disableconsole");
1875
	}
1876
}
1877

    
1878
function system_dmesg_save() {
1879
	global $g;
1880
	if(isset($config['system']['developerspew'])) {
1881
		$mt = microtime();
1882
		echo "system_dmesg_save() being called $mt\n";
1883
	}
1884

    
1885
	$dmesg = "";
1886
	$_gb = exec("/sbin/dmesg", $dmesg);
1887

    
1888
	/* find last copyright line (output from previous boots may be present) */
1889
	$lastcpline = 0;
1890

    
1891
	for ($i = 0; $i < count($dmesg); $i++) {
1892
		if (strstr($dmesg[$i], "Copyright (c) 1992-"))
1893
			$lastcpline = $i;
1894
	}
1895

    
1896
	$fd = fopen("{$g['varlog_path']}/dmesg.boot", "w");
1897
	if (!$fd) {
1898
		printf(gettext("Error: cannot open dmesg.boot in system_dmesg_save().%s"), "\n");
1899
		return 1;
1900
	}
1901

    
1902
	for ($i = $lastcpline; $i < count($dmesg); $i++)
1903
		fwrite($fd, $dmesg[$i] . "\n");
1904

    
1905
	fclose($fd);
1906
	unset($dmesg);
1907

    
1908
	return 0;
1909
}
1910

    
1911
function system_set_harddisk_standby() {
1912
	global $g, $config;
1913
	if(isset($config['system']['developerspew'])) {
1914
		$mt = microtime();
1915
		echo "system_set_harddisk_standby() being called $mt\n";
1916
	}
1917

    
1918
	if (isset($config['system']['harddiskstandby'])) {
1919
		if (platform_booting()) {
1920
			echo gettext('Setting hard disk standby... ');
1921
		}
1922

    
1923
		$standby = $config['system']['harddiskstandby'];
1924
		// Check for a numeric value
1925
		if (is_numeric($standby)) {
1926
			// Sync the disk(s)
1927
			pfSense_sync();
1928
			if (set_single_sysctl('hw.ata.standby', (int)$standby)) {
1929
				// Reinitialize ATA-drives
1930
				mwexec('/usr/local/sbin/atareinit');
1931
				if (platform_booting()) {
1932
					echo gettext("done.") . "\n";
1933
				}
1934
			} else if (platform_booting()) {
1935
				echo gettext("failed!") . "\n";
1936
			}
1937
		} else if (platform_booting()) {
1938
			echo gettext("failed!") . "\n";
1939
		}
1940
	}
1941
}
1942

    
1943
function system_setup_sysctl() {
1944
	global $config;
1945
	if(isset($config['system']['developerspew'])) {
1946
		$mt = microtime();
1947
		echo "system_setup_sysctl() being called $mt\n";
1948
	}
1949

    
1950
	activate_sysctls();	
1951

    
1952
	if (isset($config['system']['sharednet'])) {
1953
		system_disable_arp_wrong_if();
1954
	}
1955
}
1956

    
1957
function system_disable_arp_wrong_if() {
1958
	global $config;
1959
	if(isset($config['system']['developerspew'])) {
1960
		$mt = microtime();
1961
		echo "system_disable_arp_wrong_if() being called $mt\n";
1962
	}
1963
	set_sysctl(array(
1964
		"net.link.ether.inet.log_arp_wrong_iface" => "0",
1965
		"net.link.ether.inet.log_arp_movements" => "0"
1966
	));
1967
}
1968

    
1969
function system_enable_arp_wrong_if() {
1970
	global $config;
1971
	if(isset($config['system']['developerspew'])) {
1972
		$mt = microtime();
1973
		echo "system_enable_arp_wrong_if() being called $mt\n";
1974
	}
1975
	set_sysctl(array(
1976
		"net.link.ether.inet.log_arp_wrong_iface" => "1",
1977
		"net.link.ether.inet.log_arp_movements" => "1"
1978
	));
1979
}
1980

    
1981
function enable_watchdog() {
1982
	global $config;
1983
	return;
1984
	$install_watchdog = false;
1985
	$supported_watchdogs = array("Geode");
1986
	$file = file_get_contents("/var/log/dmesg.boot");
1987
	foreach($supported_watchdogs as $sd) {
1988
		if(stristr($file, "Geode")) {
1989
			$install_watchdog = true;
1990
		}
1991
	}
1992
	if($install_watchdog == true) {
1993
		if(is_process_running("watchdogd"))
1994
			mwexec("/usr/bin/killall watchdogd", true);
1995
		exec("/usr/sbin/watchdogd");
1996
	}
1997
}
1998

    
1999
function system_check_reset_button() {
2000
	global $g;
2001

    
2002
	$specplatform = system_identify_specific_platform();
2003

    
2004
	switch ($specplatform['name']) {
2005
	case 'alix':
2006
	case 'wrap':
2007
	case 'FW7541':
2008
	case 'APU':
2009
	case 'RCC-VE':
2010
	case 'RCC-DFF':
2011
		break;
2012
	default:
2013
		return 0;
2014
	}
2015

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

    
2018
	if ($retval == 99) {
2019
		/* user has pressed reset button for 2 seconds - 
2020
		   reset to factory defaults */
2021
		echo <<<EOD
2022

    
2023
***********************************************************************
2024
* Reset button pressed - resetting configuration to factory defaults. *
2025
* The system will reboot after this completes.                        *
2026
***********************************************************************
2027

    
2028

    
2029
EOD;
2030
		
2031
		reset_factory_defaults();
2032
		system_reboot_sync();
2033
		exit(0);
2034
	}
2035

    
2036
	return 0;
2037
}
2038

    
2039
/* attempt to identify the specific platform (for embedded systems)
2040
   Returns an array with two elements:
2041
	name => platform string (e.g. 'wrap', 'alix' etc.)
2042
	descr => human-readable description (e.g. "PC Engines WRAP")
2043
*/
2044
function system_identify_specific_platform() {
2045
	global $g;
2046
	
2047
	if ($g['platform'] == 'generic-pc')
2048
		return array('name' => 'generic-pc', 'descr' => gettext("Generic PC"));
2049
	
2050
	if ($g['platform'] == 'generic-pc-cdrom')
2051
		return array('name' => 'generic-pc-cdrom', 'descr' => gettext("Generic PC (CD-ROM)"));
2052
	
2053
	/* Try to guess from smbios strings */
2054
	unset($output);
2055
	$_gb = exec('/bin/kenv smbios.system.product 2>/dev/null', $output);
2056
	switch ($output[0]) {
2057
	case 'FW7541':
2058
		return (array('name' => 'FW7541', 'descr' => 'Netgate FW7541'));
2059
		break;
2060
	case 'APU':
2061
		return (array('name' => 'APU', 'descr' => 'Netgate APU'));
2062
		break;
2063
	case 'RCC-VE':
2064
		return (array('name' => 'RCC-VE', 'descr' => 'Netgate RCC-VE'));
2065
		break;
2066
	case 'DFFv2':
2067
		return (array('name' => 'RCC-DFF', 'descr' => 'Netgate RCC-DFF'));
2068
		break;
2069
	case 'SYS-5018A-FTN4':
2070
	case 'A1SAi':
2071
		return (array('name' => 'C2758', 'descr' => 'Super Micro C2758'));
2072
		break;
2073
	case 'SYS-5018D-FN4T':
2074
		return (array('name' => 'D1540-XG', 'descr' => 'Super Micro D1540-XG'));
2075
		break;
2076
	}
2077

    
2078
	/* the rest of the code only deals with 'embedded' platforms */
2079
	if ($g['platform'] != 'nanobsd')
2080
		return array('name' => $g['platform'], 'descr' => $g['platform']);
2081

    
2082
	$dmesg = get_single_sysctl('hw.model');
2083

    
2084
	if (strpos($dmesg, "PC Engines WRAP") !== false)
2085
		return array('name' => 'wrap', 'descr' => gettext('PC Engines WRAP'));
2086
	
2087
	if (strpos($dmesg, "PC Engines ALIX") !== false)
2088
		return array('name' => 'alix', 'descr' => gettext('PC Engines ALIX'));
2089

    
2090
	if (preg_match("/Soekris net45../", $dmesg, $matches))
2091
		return array('name' => 'net45xx', 'descr' => $matches[0]);
2092
	
2093
	if (preg_match("/Soekris net48../", $dmesg, $matches))
2094
		return array('name' => 'net48xx', 'descr' => $matches[0]);
2095
		
2096
	if (preg_match("/Soekris net55../", $dmesg, $matches))
2097
		return array('name' => 'net55xx', 'descr' => $matches[0]);
2098

    
2099
	unset($dmesg);
2100

    
2101
	$dmesg_boot = system_get_dmesg_boot();
2102
	if (strpos($dmesg_boot, "PC Engines ALIX") !== false)
2103
		return array('name' => 'alix', 'descr' => gettext('PC Engines ALIX'));
2104
	unset($dmesg_boot);
2105

    
2106
	/* unknown embedded platform */
2107
	return array('name' => 'embedded', 'descr' => gettext('embedded (unknown)'));
2108
}
2109

    
2110
function system_get_dmesg_boot() {
2111
	global $g;
2112
		
2113
	return file_get_contents("{$g['varlog_path']}/dmesg.boot");
2114
}
2115

    
2116
function get_possible_listen_ips($include_ipv6_link_local=false) {
2117
	$interfaces = get_configured_interface_with_descr();
2118
	$carplist = get_configured_carp_interface_list();
2119
	$listenips = array();
2120
	foreach ($carplist as $cif => $carpip)
2121
		$interfaces[$cif] = $carpip." (".get_vip_descr($carpip).")";
2122
	$aliaslist = get_configured_ip_aliases_list();
2123
	foreach ($aliaslist as $aliasip => $aliasif)
2124
		$interfaces[$aliasip] = $aliasip." (".get_vip_descr($aliasip).")";
2125
	foreach ($interfaces as $iface => $ifacename) {
2126
		$tmp["name"]  = $ifacename;
2127
		$tmp["value"] = $iface;
2128
		$listenips[] = $tmp;
2129
		if ($include_ipv6_link_local) {
2130
			$llip = find_interface_ipv6_ll(get_real_interface($iface));
2131
			if (!empty($llip)) {
2132
				$tmp["name"]  = "{$ifacename} IPv6 Link-Local";
2133
				$tmp["value"] = $llip;
2134
				$listenips[] = $tmp;
2135
			}
2136
		}
2137
	}
2138
	$tmp["name"]  = "Localhost";
2139
	$tmp["value"] = "lo0";
2140
	$listenips[] = $tmp;
2141
	return $listenips;
2142
}
2143

    
2144
function get_possible_traffic_source_addresses($include_ipv6_link_local=false) {
2145
	global $config;
2146
	$sourceips = get_possible_listen_ips($include_ipv6_link_local);
2147
	foreach (array('server', 'client') as $mode) {
2148
		if (is_array($config['openvpn']["openvpn-{$mode}"])) {
2149
			foreach ($config['openvpn']["openvpn-{$mode}"] as $id => $setting) {
2150
				if (!isset($setting['disable'])) {
2151
					$vpn = array();
2152
					$vpn['value'] = 'ovpn' . substr($mode, 0, 1) . $setting['vpnid'];
2153
					$vpn['name'] = gettext("OpenVPN") . " ".$mode.": ".htmlspecialchars($setting['description']);
2154
					$sourceips[] = $vpn;
2155
				}
2156
			}
2157
		}
2158
	}
2159
	return $sourceips;
2160
}
2161
?>
(53-53/68)