system.inc 56.4 KB
Newer Older
Ad Schellevis's avatar
Ad Schellevis committed
1
<?php
2

Ad Schellevis's avatar
Ad Schellevis committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
	All rights reserved.

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

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

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

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

29 30
function activate_powerd()
{
Franco Fichtner's avatar
Franco Fichtner committed
31
	global $config;
32 33 34 35 36

	if (is_process_running('powerd')) {
		exec('/usr/bin/killall powerd');
	}

Ad Schellevis's avatar
Ad Schellevis committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
	if(isset($config['system']['powerd_enable'])) {
		$ac_mode = "hadp";
		if (!empty($config['system']['powerd_ac_mode']))
			$ac_mode = $config['system']['powerd_ac_mode'];

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

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

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

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
function get_default_sysctl_value($id)
{
	$sysctls = array(
		"debug.pfftpproxy" => "0",
		"hw.syscons.kbd_reboot" => "0",
		"kern.ipc.maxsockbuf" => "4262144",
		"kern.randompid" => "347",
		"kern.random.sys.harvest.interrupt" => 0,
		"kern.random.sys.harvest.point_to_point" => 0,
		"kern.random.sys.harvest.ethernet" => 0,
		"kern.filedelay" => "5",
		"kern.dirdelay" => "4",
		"kern.metadelay" => "3",
		"net.bpf.zerocopy_enable" => 1,
		"net.inet.ip.portrange.first" => "1024",
		"net.inet.tcp.blackhole" => "2",
		"net.inet.udp.blackhole" => "1",
		"net.inet.ip.random_id" => "1",
		"net.inet.tcp.drop_synfin" => "1",
		"net.inet.ip.redirect" => "1",
		"net.inet6.ip6.redirect" => "1",
		"net.inet6.ip6.use_tempaddr" => "0",
		"net.inet6.ip6.prefer_tempaddr" => "0",
		"net.inet.tcp.syncookies" => "1",
		"net.inet.tcp.recvspace" => "65228",
		"net.inet.tcp.sendspace" => "65228",
		"net.inet.ip.fastforwarding" => "0",
81 82 83 84
		'net.inet.ip.sourceroute' => '0',
		'net.inet.ip.accept_sourceroute' => '0',
		'net.inet.icmp.drop_redirect' => '0',
		'net.inet.icmp.log_redirect' => '0',
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
		"net.inet.tcp.delayed_ack" => "0",
		"net.inet.udp.maxdgram" => "57344",
		"net.inet.ip.intr_queue_maxlen" => "1000",
		"net.inet.tcp.log_debug" => "0",
		"net.inet.tcp.tso" => "1",
		"net.inet.icmp.icmplim" => "0",
		"net.inet.ip.process_options" => 0,
		"net.inet.udp.checksum" => 1,
		"net.link.bridge.pfil_onlyip" => "0",
		"net.link.bridge.pfil_member" => "1",
		"net.link.bridge.pfil_bridge" => "0",
		"net.link.tap.user_open" => "1",
		"net.route.netisr_maxqlen" => 1024,
		"net.inet.icmp.reply_from_interface" => 1,
		"vfs.read_max" => "32",
	);
Ad Schellevis's avatar
Ad Schellevis committed
101

102
	if (isset($sysctls[$id])) {
Ad Schellevis's avatar
Ad Schellevis committed
103
		return $sysctls[$id];
104 105 106
	}

	return null;
Ad Schellevis's avatar
Ad Schellevis committed
107 108
}

109 110
function activate_sysctls()
{
Franco Fichtner's avatar
Franco Fichtner committed
111
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
112 113

	$sysctls = array(
114 115
		"net.enc.in.ipsec_bpf_mask" => "0x0002",
		"net.enc.in.ipsec_filter_mask" => "0x0002",
Ad Schellevis's avatar
Ad Schellevis committed
116 117 118 119
		"net.enc.out.ipsec_bpf_mask" => "0x0001",
		"net.enc.out.ipsec_filter_mask" => "0x0001",
	);

120
	if (isset($config['sysctl']['item'])) {
Ad Schellevis's avatar
Ad Schellevis committed
121
		foreach($config['sysctl']['item'] as $tunable) {
122
			if ($tunable['value'] == 'default') {
Ad Schellevis's avatar
Ad Schellevis committed
123
				$value = get_default_sysctl_value($tunable['tunable']);
124
			} else {
Ad Schellevis's avatar
Ad Schellevis committed
125
				$value = $tunable['value'];
126
			}
Ad Schellevis's avatar
Ad Schellevis committed
127

128
			$sysctls[$tunable['tunable']] = $value;
Ad Schellevis's avatar
Ad Schellevis committed
129 130 131 132 133 134
		}
	}

	set_sysctl($sysctls);
}

135 136
function system_resolvconf_generate($dynupdate = false)
{
Franco Fichtner's avatar
Franco Fichtner committed
137
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

	$syscfg = $config['system'];

	// Do not create blank domain lines, it breaks tools like dig.
	if($syscfg['domain'])
		$resolvconf = "domain {$syscfg['domain']}\n";

	if (((isset($config['dnsmasq']['enable']) && (empty($config['dnsmasq']['interface']) || in_array("lo0", explode(",", $config['dnsmasq']['interface']))))
		|| (isset($config['unbound']['enable'])) && (empty($config['unbound']['active_interface']) || in_array("lo0", explode(",", $config['unbound']['active_interface']))))
		&& !isset($config['system']['dnslocalhost']))
		$resolvconf .= "nameserver 127.0.0.1\n";

	if (isset($syscfg['dnsallowoverride'])) {
		/* get dynamically assigned DNS servers (if any) */
		$ns = array_unique(get_searchdomains());
		foreach($ns as $searchserver) {
			if($searchserver)
				$resolvconf .= "search {$searchserver}\n";
		}
		$ns = array_unique(get_nameservers());
		foreach($ns as $nameserver) {
			if($nameserver)
				$resolvconf .= "nameserver $nameserver\n";
		}
	}
163
	if (isset($syscfg['dnsserver']) && is_array($syscfg['dnsserver'])) {
Ad Schellevis's avatar
Ad Schellevis committed
164 165 166 167 168 169 170 171 172 173 174 175
		foreach ($syscfg['dnsserver'] as $ns) {
			if ($ns)
				$resolvconf .= "nameserver $ns\n";
		}
	}

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

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

176
	$fd = fopen('/etc/resolv.conf', 'w');
Ad Schellevis's avatar
Ad Schellevis committed
177 178 179 180 181 182 183 184
	if (!$fd) {
		printf("Error: cannot open resolv.conf in system_resolvconf_generate().\n");
		unlock($dnslock);
		return 1;
	}

	fwrite($fd, $resolvconf);
	fclose($fd);
185
	chmod('/etc/resolv.conf', 0644);
Ad Schellevis's avatar
Ad Schellevis committed
186

Ad Schellevis's avatar
Ad Schellevis committed
187
	if (!file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
		/* restart dhcpd (nameservers may have changed) */
		if (!$dynupdate)
			services_dhcpd_configure();
	}

	/* setup static routes for DNS servers. */
	for ($dnscounter=1; $dnscounter<5; $dnscounter++) {
		/* setup static routes for dns servers */
		$dnsgw = "dns{$dnscounter}gw";
		if (isset($config['system'][$dnsgw])) {
			$gwname = $config['system'][$dnsgw];
			if (($gwname <> "") && ($gwname <> "none")) {
				$gatewayip = lookup_gateway_ip_by_name($gwname);
				if (is_ipaddrv4($gatewayip)) {
					/* dns server array starts at 0 */
					$dnscountermo = $dnscounter - 1;
204 205
					mwexec("/sbin/route delete -host " . $syscfg['dnsserver'][$dnscountermo]);
					mwexec("/sbin/route add -host " . $syscfg['dnsserver'][$dnscountermo] . " {$gatewayip}");
Ad Schellevis's avatar
Ad Schellevis committed
206 207 208 209
				}
				if (is_ipaddrv6($gatewayip)) {
					/* dns server array starts at 0 */
					$dnscountermo = $dnscounter - 1;
210 211
					mwexec("/sbin/route delete -host -inet6 " . $syscfg['dnsserver'][$dnscountermo]);
					mwexec("/sbin/route add -host -inet6 " . $syscfg['dnsserver'][$dnscountermo] . " {$gatewayip}");
Ad Schellevis's avatar
Ad Schellevis committed
212 213 214 215 216 217 218 219 220 221
				}
			}
		}
	}

	unlock($dnslock);

	return 0;
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
function get_country_codes()
{
    $dn_cc = array();

    $iso3166_tab = '/usr/local/opnsense/contrib/tzdata/iso3166.tab';
    if (file_exists($iso3166_tab)) {
        $dn_cc_file = file($iso3166_tab);
        foreach ($dn_cc_file as $line) {
            if (preg_match('/^([A-Z][A-Z])\t(.*)$/', $line, $matches)) {
                $dn_cc[$matches[1]] = trim($matches[2]);
            }
        }
    }

    return $dn_cc;
}

239 240 241 242 243
function get_firmware_mirrors()
{
	$mirrors = array();

	$mirrors['default'] = '(default)';
244
	$mirrors['https://opnsense.aivian.org'] = 'Aivian (Shaoxing, CN)';
245 246 247 248 249 250 251 252
	$mirrors['https://opnsense.c0urier.net'] = 'c0urier.net (Lund, SE)';
	$mirrors['https://fleximus.org/mirror/opnsense'] = 'Fleximus (Roubaix, FR)';
	$mirrors['http://mirror.ams1.nl.leaseweb.net/opnsense'] = 'LeaseWeb (Amsterdam, NL)';
	$mirrors['http://mirror.fra10.de.leaseweb.net/opnsense'] = 'LeaseWeb (Frankfurt, DE)';
	$mirrors['http://mirror.sfo12.us.leaseweb.net/opnsense'] = 'LeaseWeb (San Francisco, US)';
	$mirrors['http://mirror.wdc1.us.leaseweb.net/opnsense'] = 'LeaseWeb (Washington, D.C., US)';
	$mirrors['http://mirrors.nycbug.org/pub/opnsense'] = 'NYC*BUG (New York, US)';
	$mirrors['http://pkg.opnsense.org'] = 'OPNsense (Amsterdam, NL)';
253
	$mirrors['http://mirrors.supranet.net/pub/opnsense'] = 'Supranet Communications (Middleton, US)';
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

	return $mirrors;
}

function get_firmware_flavours()
{
	$flavours = array();

	$flavours['default'] = '(default)';
	$flavours['libressl'] = 'LibreSSL';
	$flavours['latest'] = 'OpenSSL';

	return $flavours;
}

269 270
function get_zoneinfo()
{
271
	return timezone_identifiers_list(DateTimeZone::ALL ^ DateTimeZone::UTC);
272 273
}

Franco Fichtner's avatar
Franco Fichtner committed
274 275 276
function get_searchdomains()
{
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
277 278

	$master_list = array();
279

Ad Schellevis's avatar
Ad Schellevis committed
280 281 282 283 284 285 286 287
	// Read in dhclient nameservers
	$search_list = glob("/var/etc/searchdomain_*");
	if (is_array($search_list)) {
		foreach($search_list as $fdns) {
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
			if (!is_array($contents))
				continue;
			foreach ($contents as $dns) {
288
				if(is_hostname($dns))
Ad Schellevis's avatar
Ad Schellevis committed
289 290 291 292 293 294 295 296
					$master_list[] = $dns;
			}
		}
	}

	return $master_list;
}

Franco Fichtner's avatar
Franco Fichtner committed
297 298 299
function get_nameservers()
{
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
300
	$master_list = array();
301

Ad Schellevis's avatar
Ad Schellevis committed
302 303 304 305 306 307 308 309
	// Read in dhclient nameservers
	$dns_lists = glob("/var/etc/nameserver_*");
	if (is_array($dns_lists)) {
		foreach($dns_lists as $fdns) {
			$contents = file($fdns, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
			if (!is_array($contents))
				continue;
			foreach ($contents as $dns) {
310
				if(is_ipaddr($dns))
Ad Schellevis's avatar
Ad Schellevis committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
					$master_list[] = $dns;
			}
		}
	}

	// Read in any extra nameservers
	if(file_exists("/var/etc/nameservers.conf")) {
		$dns_s = file("/var/etc/nameservers.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
		if(is_array($dns_s)) {
			foreach($dns_s as $dns)
				if (is_ipaddr($dns))
					$master_list[] = $dns;
		}
	}

	return $master_list;
}

329 330
function system_hosts_generate()
{
Franco Fichtner's avatar
Franco Fichtner committed
331
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
332 333 334 335 336 337 338 339

	$syscfg = $config['system'];
	$dnsmasqcfg = $config['dnsmasq'];

	$hosts = "127.0.0.1	localhost localhost.{$syscfg['domain']}\n";
	$lhosts = "";
	$dhosts = "";

340
	if (isset($config['interfaces']['lan'])) {
Ad Schellevis's avatar
Ad Schellevis committed
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
		$cfgip = get_interface_ip("lan");
		if (is_ipaddr($cfgip))
			$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
	} else {
		$sysiflist = get_configured_interface_list();
		foreach ($sysiflist as $sysif) {
			if (!interface_has_gateway($sysif)) {
				$cfgip = get_interface_ip($sysif);
				if (is_ipaddr($cfgip)) {
					$hosts .= "{$cfgip}	{$syscfg['hostname']}.{$syscfg['domain']} {$syscfg['hostname']}\n";
					break;
				}
			}
		}
	}

	if (isset($dnsmasqcfg['enable'])) {
358
		if (!isset($dnsmasqcfg['hosts']) || !is_array($dnsmasqcfg['hosts']))
Ad Schellevis's avatar
Ad Schellevis committed
359 360 361 362 363 364 365
			$dnsmasqcfg['hosts'] = array();

		foreach ($dnsmasqcfg['hosts'] as $host) {
			if ($host['host'])
				$lhosts .= "{$host['ip']}	{$host['host']}.{$host['domain']} {$host['host']}\n";
			else
				$lhosts .= "{$host['ip']}	{$host['domain']}\n";
366
			if (!isset($host['aliases']) || !is_array($host['aliases']) || !is_array($host['aliases']['item'])) {
Ad Schellevis's avatar
Ad Schellevis committed
367
				continue;
368
			}
Ad Schellevis's avatar
Ad Schellevis committed
369 370 371 372 373 374 375 376
			foreach ($host['aliases']['item'] as $alias) {
				if ($alias['host'])
					$lhosts .= "{$host['ip']}	{$alias['host']}.{$alias['domain']} {$alias['host']}\n";
				else
					$lhosts .= "{$host['ip']}	{$alias['domain']}\n";
			}
		}
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpd'])) {
377 378 379 380 381 382 383 384 385 386 387 388 389
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
				if (isset($dhcpifconf['staticmap']) && isset($dhcpifconf['enable'])) {
					foreach ($dhcpifconf['staticmap'] as $host) {
						if ($host['ipaddr'] && $host['hostname'] && $host['domain']) {
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
						} elseif ($host['ipaddr'] && $host['hostname'] && $dhcpifconf['domain']) {
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
						} elseif ($host['ipaddr'] && $host['hostname']) {
							$dhosts .= "{$host['ipaddr']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
						}
					}
				}
			}
Ad Schellevis's avatar
Ad Schellevis committed
390 391
		}
		if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpdv6'])) {
392 393 394 395 396 397 398 399 400 401 402 403 404
			foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) {
				if (isset($dhcpifconf['staticmap']) && isset($dhcpifconf['enable'])) {
					foreach ($dhcpifconf['staticmap'] as $host) {
						if ($host['ipaddrv6'] && $host['hostname'] && $host['domain']) {
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$host['domain']} {$host['hostname']}\n";
						} elseif ($host['ipaddrv6'] && $host['hostname'] && $dhcpifconf['domain']) {
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n";
						} elseif ($host['ipaddrv6'] && $host['hostname']) {
							$dhosts .= "{$host['ipaddrv6']}	{$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n";
						}
					}
				}
			}
Ad Schellevis's avatar
Ad Schellevis committed
405 406
		}

407
		if (isset($dnsmasqcfg['dhcpfirst'])) {
Ad Schellevis's avatar
Ad Schellevis committed
408
			$hosts .= $dhosts . $lhosts;
409
		} else {
Ad Schellevis's avatar
Ad Schellevis committed
410
			$hosts .= $lhosts . $dhosts;
411
		}
Ad Schellevis's avatar
Ad Schellevis committed
412 413 414
	}

	/*
415 416
	 * Do not remove this because dhcpleases monitors with kqueue
	 * it needs to be * killed before writing to hosts files.
Ad Schellevis's avatar
Ad Schellevis committed
417
	 */
418
	killbypid('/var/run/dhcpleases.pid');
419

420
	$fd = fopen('/etc/hosts', 'w');
Ad Schellevis's avatar
Ad Schellevis committed
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	if (!$fd) {
		log_error("Error: cannot open hosts file in system_hosts_generate().\n");
		return 1;
	}
	fwrite($fd, $hosts);
	fclose($fd);

	if (isset($config['unbound']['enable'])) {
		unbound_hosts_generate();
	}

	system_dhcpleases_configure();

	return 0;
}

437 438
function system_dhcpleases_configure()
{
Ad Schellevis's avatar
Ad Schellevis committed
439
	global $config, $g;
440

Ad Schellevis's avatar
Ad Schellevis committed
441
	/* Start the monitoring process for dynamic dhcpclients. */
442
	if ((isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcp']))
Ad Schellevis's avatar
Ad Schellevis committed
443 444 445
		|| (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcp']))) {
		/* Make sure we do not error out */
		mwexec("/bin/mkdir -p {$g['dhcpd_chroot_path']}/var/db");
446
		if (!file_exists("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases")) {
Ad Schellevis's avatar
Ad Schellevis committed
447
			@touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
448
		}
449 450
		if (isvalidpid('/var/run/dhcpleases.pid')) {
			killbypid('/var/run/dhcpleases.pid', 'HUP');
451
		} else {
Ad Schellevis's avatar
Ad Schellevis committed
452
			/* To ensure we do not start multiple instances of dhcpleases, perform some clean-up first. */
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
			killbyname('dhcpleases');
			@unlink('/var/run/dhcpleases.pid');
			if (isset($config['unbound']['enable'])) {
				$dns_pid = 'unbound.pid';
			} else {
				$dns_pid = 'dnsmasq.pid';
			}
			mwexecf(
				'/usr/local/sbin/dhcpleases -l %s -d %s -p %s -h %s',
				array(
					"{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases",
					$config['system']['domain'],
					"/var/run/{$dns_pid}",
					'/etc/hosts'
				)
			);
Ad Schellevis's avatar
Ad Schellevis committed
469 470
		}
	} else {
471
		killbypid('/var/run/dhcpleases.pid');
Ad Schellevis's avatar
Ad Schellevis committed
472 473 474
	}
}

475 476
function system_hostname_configure()
{
Franco Fichtner's avatar
Franco Fichtner committed
477
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
478 479 480 481 482 483 484 485 486 487 488 489 490

	$syscfg = $config['system'];

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

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

	return $status;
}

491 492
function system_routing_configure($interface = '')
{
Franco Fichtner's avatar
Franco Fichtner committed
493
	global $config;
494

Ad Schellevis's avatar
Ad Schellevis committed
495 496 497 498 499 500 501
	$gatewayip = "";
	$interfacegw = "";
	$foundgw = false;
	$gatewayipv6 = "";
	$interfacegwv6 = "";
	$foundgwv6 = false;
	/* tack on all the hard defined gateways as well */
502
	if (isset($config['gateways']['gateway_item'])) {
503
		array_map('unlink', glob('/tmp/*_defaultgw{,v6}', GLOB_BRACE));
Ad Schellevis's avatar
Ad Schellevis committed
504 505 506 507 508 509 510 511 512 513 514 515
		foreach	($config['gateways']['gateway_item'] as $gateway) {
			if (isset($gateway['defaultgw'])) {
				if ($gateway['ipprotocol'] != "inet6" && (is_ipaddrv4($gateway['gateway']) || $gateway['gateway'] == "dynamic")) {
					if(strstr($gateway['gateway'], ":"))
						continue;
					if ($gateway['gateway'] == "dynamic")
						$gateway['gateway'] = get_interface_gateway($gateway['interface']);
					$gatewayip = $gateway['gateway'];
					$interfacegw = $gateway['interface'];
					if (!empty($gateway['interface'])) {
						$defaultif = get_real_interface($gateway['interface']);
						if ($defaultif)
516
							@file_put_contents("/tmp/{$defaultif}_defaultgw", $gateway['gateway']);
Ad Schellevis's avatar
Ad Schellevis committed
517 518 519 520 521 522 523 524 525 526
					}
					$foundgw = true;
				} else if ($gateway['ipprotocol'] == "inet6" && (is_ipaddrv6($gateway['gateway']) || $gateway['gateway'] == "dynamic")) {
					if ($gateway['gateway'] == "dynamic")
						$gateway['gateway'] = get_interface_gateway_v6($gateway['interface']);
					$gatewayipv6 = $gateway['gateway'];
					$interfacegwv6 = $gateway['interface'];
					if (!empty($gateway['interface'])) {
						$defaultifv6 = get_real_interface($gateway['interface']);
						if ($defaultifv6)
527
							@file_put_contents("/tmp/{$defaultifv6}_defaultgwv6", $gateway['gateway']);
Ad Schellevis's avatar
Ad Schellevis committed
528 529 530 531 532 533 534 535
					}
					$foundgwv6 = true;
				}
			}
			if ($foundgw === true && $foundgwv6 === true)
				break;
		}
	}
536
	if (!$foundgw) {
Ad Schellevis's avatar
Ad Schellevis committed
537 538 539
		$defaultif = get_real_interface("wan");
		$interfacegw = "wan";
		$gatewayip = get_interface_gateway("wan");
540
		@touch("/tmp/{$defaultif}_defaultgw");
541
	}
542
	if (!$foundgwv6) {
Ad Schellevis's avatar
Ad Schellevis committed
543 544 545
		$defaultifv6 = get_real_interface("wan");
		$interfacegwv6 = "wan";
		$gatewayipv6 = get_interface_gateway_v6("wan");
546
		@touch("/tmp/{$defaultif}_defaultgwv6");
Ad Schellevis's avatar
Ad Schellevis committed
547 548
	}

549 550 551 552 553 554 555 556
	if (!empty($interface) && $interface != $interfacegw)
		;
	else if (is_ipaddrv4($gatewayip)) {
		log_error("ROUTING: remove current default route to $gatewayip");
		mwexec("/sbin/route delete default");
		log_error("ROUTING: setting default route to $gatewayip");
		mwexec("/sbin/route add -inet default " . escapeshellarg($gatewayip));
	}
Ad Schellevis's avatar
Ad Schellevis committed
557

558 559 560 561 562 563 564 565 566
	if (!empty($interface) && $interface != $interfacegwv6)
		;
	else if (is_ipaddrv6($gatewayipv6)) {
		$ifscope = "";
		if (is_linklocal($gatewayipv6))
			$ifscope = "%{$defaultifv6}";
		log_error("ROUTING: setting IPv6 default route to {$gatewayipv6}{$ifscope}");
		mwexec("/sbin/route delete -inet6 default " . escapeshellarg("{$gatewayipv6}{$ifscope}"));
		mwexec("/sbin/route add -inet6 default " . escapeshellarg("{$gatewayipv6}{$ifscope}"));
Ad Schellevis's avatar
Ad Schellevis committed
567 568 569 570 571 572 573
	}

	system_staticroutes_configure($interface, false);

	return 0;
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
/* Compare the current hostname DNS to the DNS cache we made
 * if it has changed we return the old records
 * if no change we return false */
function compare_hostname_to_dnscache($hostname) {
        if(!is_dir("/var/db/dnscache")) {
                mkdir("/var/db/dnscache");
        }
        $hostname = trim($hostname);
        if(is_readable("/var/db/dnscache/{$hostname}")) {
                $oldcontents = file_get_contents("/var/db/dnscache/{$hostname}");
        } else {
                $oldcontents = "";
        }
        if((is_fqdn($hostname)) && (!is_ipaddr($hostname))) {
                $domrecords = array();
                $domips = array();
                exec("host -t A " . escapeshellarg($hostname), $domrecords, $rethost);
                if($rethost == 0) {
                        foreach($domrecords as $domr) {
                                $doml = explode(" ", $domr);
                                $domip = $doml[3];
                                /* fill array with domain ip addresses */
                                if(is_ipaddr($domip)) {
                                        $domips[] = $domip;
                                }
                        }
                }
                sort($domips);
                $contents = "";
                if(! empty($domips)) {
                        foreach($domips as $ip) {
                                $contents .= "$ip\n";
                        }
                }
        }

        if(trim($oldcontents) != trim($contents)) {
611
                log_error(sprintf(gettext('DNSCACHE: Found old IP %s and new IP %s'), $oldcontents, $contents));
612 613 614 615 616 617
                return ($oldcontents);
        } else {
                return false;
        }
}

Franco Fichtner's avatar
Franco Fichtner committed
618 619 620
function system_staticroutes_configure($interface = '', $update_dns = false)
{
	global $config, $aliastable;
Ad Schellevis's avatar
Ad Schellevis committed
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684

	$filterdns_list = array();

	$static_routes = get_staticroutes(false, true);
	if (count($static_routes)) {
		$gateways_arr = return_gateways_array(false, true);

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

			$gatewayip = $gateway['gateway'];
			$interfacegw = $gateway['interface'];

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

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

			$dnscache = array();
			if ($update_dns === true) {
				if (is_subnet($rtent['network']))
					continue;
				$dnscache = explode("\n", trim(compare_hostname_to_dnscache($rtent['network'])));
				if (empty($dnscache))
					continue;
			}

			if (is_subnet($rtent['network']))
				$ips = array($rtent['network']);
			else {
				if (!isset($rtent['disabled']))
					$filterdns_list[] = $rtent['network'];
				$ips = add_hostname_to_watch($rtent['network']);
			}

			foreach ($dnscache as $ip) {
				if (in_array($ip, $ips))
					continue;
				mwexec("/sbin/route delete " . escapeshellarg($ip), true);
			}

			if (isset($rtent['disabled'])) {
				/* XXX: This is a bit dangerous in case of routing daemons!? */
				foreach ($ips as $ip)
					mwexec("/sbin/route delete " . escapeshellarg($ip), true);
				continue;
			}

			foreach ($ips as $ip) {
				if (is_ipaddrv4($ip))
					$ip .= "/32";
				else if (is_ipaddrv6($ip))
					$ip .= "/128";

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

685
				$cmd = " {$inet} {$blackhole} " . escapeshellarg($ip) . " ";
Ad Schellevis's avatar
Ad Schellevis committed
686 687

				if (is_subnet($ip))
688
					if (is_ipaddr($gatewayip)) {
689 690
						mwexec("/sbin/route delete".$cmd . escapeshellarg($gatewayip));
						mwexec("/sbin/route add".$cmd . escapeshellarg($gatewayip));
691 692
					}
					else if (!empty($interfacegw)) {
693 694
						mwexec("/sbin/route delete".$cmd . "-iface " . escapeshellarg($interfacegw));
						mwexec("/sbin/route add".$cmd . "-iface " . escapeshellarg($interfacegw));
695
					}
Ad Schellevis's avatar
Ad Schellevis committed
696 697 698 699 700 701 702 703 704 705 706 707
			}
		}
		unset($gateways_arr);
	}
	unset($static_routes);

	if ($update_dns === false) {
		if (count($filterdns_list)) {
			$interval = 60;
			$hostnames = "";
			array_unique($filterdns_list);
			foreach ($filterdns_list as $hostname)
708
				$hostnames .= "cmd {$hostname} '/usr/local/opnsense/service/configd_ctl.py routedns reload'\n";
709
			file_put_contents("/var/etc/filterdns-route.hosts", $hostnames);
Ad Schellevis's avatar
Ad Schellevis committed
710 711
			unset($hostnames);

712 713
			if (isvalidpid('/var/run/filterdns-route.pid')) {
				killbypid('/var/run/filterdns-route.pid', 'HUP');
714
			} else {
715
				mwexec("/usr/local/sbin/filterdns -p /var/run/filterdns-route.pid -i {$interval} -c /var/etc/filterdns-route.hosts -d 1");
716
			}
Ad Schellevis's avatar
Ad Schellevis committed
717
		} else {
718
			killbypid('/var/run/filterdns-route.pid');
Ad Schellevis's avatar
Ad Schellevis committed
719 720 721 722 723 724 725
		}
	}
	unset($filterdns_list);

	return 0;
}

726 727
function system_routing_enable()
{
Franco Fichtner's avatar
Franco Fichtner committed
728
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

	set_sysctl(array(
		"net.inet.ip.forwarding" => "1",
		"net.inet6.ip6.forwarding" => "1"
	));
}

function system_syslogd_fixup_server($server) {
	/* If it's an IPv6 IP alone, encase it in brackets */
	if (is_ipaddrv6($server))
		return "[$server]";
	else
		return $server;
}

function system_syslogd_get_remote_servers($syslogcfg, $facility = "*.*") {
	// Rather than repeatedly use the same code, use this function to build a list of remote servers.
	$facility .= " ".
	$remote_servers = "";
	$pad_to  = 56;
	$padding = ceil(($pad_to - strlen($facility))/8)+1;
	if($syslogcfg['remoteserver'])
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver']) . "\n";
	if($syslogcfg['remoteserver2'])
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver2']) . "\n";
	if($syslogcfg['remoteserver3'])
		$remote_servers .= "{$facility}" . str_repeat("\t", $padding) . "@" . system_syslogd_fixup_server($syslogcfg['remoteserver3']) . "\n";
	return $remote_servers;
}

759 760
function system_syslogd_start()
{
Ad Schellevis's avatar
Ad Schellevis committed
761
	global $config, $g;
762
	$retval = null;
Ad Schellevis's avatar
Ad Schellevis committed
763

764 765 766
	/* XXX temporary hook for newsyslog.conf regeneration */
	configd_run('template reload OPNsense.Syslog');

767
	mwexec('/etc/rc.d/hostid start');
Ad Schellevis's avatar
Ad Schellevis committed
768 769 770

	$syslogcfg = $config['syslog'];

771 772
	if (file_exists('/var/run/booting')) {
		echo gettext('Starting syslog...');
Ad Schellevis's avatar
Ad Schellevis committed
773 774
	}

775
	$log_directive = '%';
776
	$syslogd_extra = '';
777

Ad Schellevis's avatar
Ad Schellevis committed
778
	if (isset($syslogcfg)) {
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
		$separatelogfacilities = array(
			'apinger',
			'bgpd',
			'charon',
			'dhclient',
			'dhcp6c',
			'dhcpd',
			'dhcrelay',
			'dnsmasq',
			'filterdns',
			'filterlog',
			'hostapd',
			'l2tps',
			'miniupnpd',
			'ntp',
			'ntpd',
			'ntpdate',
			'olsrd',
			'openvpn',
			'ospfd',
			'poes',
			'ppp',
			'pptps',
			'radvd',
			'relayd',
			'routed',
			'unbound',
			'zebra',
		);
		$syslogconf = '';
809

Ad Schellevis's avatar
Ad Schellevis committed
810 811 812
		$facilitylist = implode(',', array_unique($separatelogfacilities));
		$syslogconf .= "!radvd,routed,olsrd,zebra,ospfd,bgpd,miniupnpd\n";
		if (!isset($syslogcfg['disablelocallogging']))
813
			$syslogconf .= "*.*								{$log_directive}/var/log/routing.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
814 815

		$syslogconf .= "!ntp,ntpd,ntpdate\n";
816
		if (!isset($syslogcfg['disablelocallogging']))
817
			$syslogconf .= "*.*								{$log_directive}/var/log/ntpd.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
818 819

		$syslogconf .= "!ppp\n";
820
		if (!isset($syslogcfg['disablelocallogging']))
821
			$syslogconf .= "*.*								{$log_directive}/var/log/ppps.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
822 823

		$syslogconf .= "!pptps\n";
824
		if (!isset($syslogcfg['disablelocallogging']))
825
			$syslogconf .= "*.*								{$log_directive}/var/log/pptps.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
826 827

		$syslogconf .= "!poes\n";
828
		if (!isset($syslogcfg['disablelocallogging']))
829
			$syslogconf .= "*.*								{$log_directive}/var/log/poes.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
830 831

		$syslogconf .= "!l2tps\n";
832
		if (!isset($syslogcfg['disablelocallogging']))
833
			$syslogconf .= "*.*								{$log_directive}/var/log/l2tps.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
834 835

		$syslogconf .= "!charon\n";
836
		if (!isset($syslogcfg['disablelocallogging']))
837
			$syslogconf .= "*.*								{$log_directive}/var/log/ipsec.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
838 839 840 841
		if (isset($syslogcfg['vpn']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!openvpn\n";
842
		if (!isset($syslogcfg['disablelocallogging']))
843
			$syslogconf .= "*.*								{$log_directive}/var/log/openvpn.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
844 845 846 847 848
		if (isset($syslogcfg['vpn']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!apinger\n";
		if (!isset($syslogcfg['disablelocallogging']))
849
			$syslogconf .= "*.*								{$log_directive}/var/log/gateways.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
850 851 852 853 854
		if (isset($syslogcfg['apinger']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!dnsmasq,filterdns,unbound\n";
		if (!isset($syslogcfg['disablelocallogging']))
855
			$syslogconf .= "*.*								{$log_directive}/var/log/resolver.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
856 857 858

		$syslogconf .= "!dhcpd,dhcrelay,dhclient,dhcp6c\n";
		if (!isset($syslogcfg['disablelocallogging']))
859
			$syslogconf .= "*.*								{$log_directive}/var/log/dhcpd.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
860 861 862 863 864
		if (isset($syslogcfg['dhcp']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!relayd\n";
		if (!isset($syslogcfg['disablelocallogging']))
865
			$syslogconf .= "*.*								{$log_directive}/var/log/relayd.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
866 867 868 869 870
		if (isset($syslogcfg['relayd']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!hostapd\n";
		if (!isset($syslogcfg['disablelocallogging']))
871
			$syslogconf .= "*.*								{$log_directive}/var/log/wireless.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
872 873 874 875
		if (isset($syslogcfg['hostapd']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!filterlog\n";
876
		$syslogconf .= "*.*								{$log_directive}/var/log/filter.log\n";
Ad Schellevis's avatar
Ad Schellevis committed
877 878 879 880
		if (isset($syslogcfg['filter']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");

		$syslogconf .= "!-{$facilitylist}\n";
881
		if (!isset($syslogcfg['disablelocallogging']))
Ad Schellevis's avatar
Ad Schellevis committed
882
			$syslogconf .= <<<EOD
883 884 885 886 887 888 889 890
local3.*							{$log_directive}/var/log/vpn.log
local4.*							{$log_directive}/var/log/portalauth.log
local7.*							{$log_directive}/var/log/dhcpd.log
*.notice;kern.debug;lpr.info;mail.crit;daemon.none;		{$log_directive}/var/log/system.log
news.err;local0.none;local3.none;local4.none;			{$log_directive}/var/log/system.log
local7.none							{$log_directive}/var/log/system.log
security.*							{$log_directive}/var/log/system.log
auth.info;authpriv.info;daemon.info				{$log_directive}/var/log/system.log
891
auth.info;authpriv.info						|exec /usr/local/sbin/sshlockout_pf 15
Ad Schellevis's avatar
Ad Schellevis committed
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
*.emerg								*

EOD;
		if (isset($syslogcfg['vpn']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local3.*");
		if (isset($syslogcfg['portalauth']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local4.*");
		if (isset($syslogcfg['dhcp']))
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "local7.*");
		if (isset($syslogcfg['system'])) {
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.notice;kern.debug;lpr.info;mail.crit;");
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "news.err;local0.none;local3.none;local7.none");
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "security.*");
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "auth.info;authpriv.info;daemon.info");
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.emerg");
		}
		if (isset($syslogcfg['logall'])) {
			// Make everything mean everything, including facilities excluded above.
			$syslogconf .= "!*\n";
			$syslogconf .= system_syslogd_get_remote_servers($syslogcfg, "*.*");
		}

914
		/* write syslog.conf */
915
		if (!@file_put_contents("/var/etc/syslog.conf", $syslogconf)) {
Ad Schellevis's avatar
Ad Schellevis committed
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
			printf(gettext("Error: cannot open syslog.conf in system_syslogd_start().%s"), "\n");
			unset($syslogconf);
			return 1;
		}
		unset($syslogconf);

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

		$sourceip = "";
		if (!empty($syslogcfg['sourceip'])) {
			if ($syslogcfg['ipproto'] == "ipv6") {
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ipv6($syslogcfg['sourceip']);
				if (!is_ipaddr($ifaddr))
					$ifaddr = get_interface_ip($syslogcfg['sourceip']);
			} else {
				$ifaddr = is_ipaddr($syslogcfg['sourceip']) ? $syslogcfg['sourceip'] : get_interface_ip($syslogcfg['sourceip']);
				if (!is_ipaddr($ifaddr))
					$ifaddr = get_interface_ipv6($syslogcfg['sourceip']);
			}
			if (is_ipaddr($ifaddr)) {
				$sourceip = "-b {$ifaddr}";
			}
		}

942
		$syslogd_extra = "-f /var/etc/syslog.conf {$sourceip}";
Ad Schellevis's avatar
Ad Schellevis committed
943 944
	}

945 946
	if (isvalidpid('/var/run/syslog.pid')) {
		killbypid('/var/run/syslog.pid', 'HUP');
947
	} else {
948
		$retval = mwexec_bg("/usr/local/sbin/syslogd -s -c -c -l {$g['dhcpd_chroot_path']}/var/run/log -P /var/run/syslog.pid {$syslogd_extra}");
949
	}
Ad Schellevis's avatar
Ad Schellevis committed
950

951
	if (file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
952
		echo gettext("done.") . "\n";
953
	}
Ad Schellevis's avatar
Ad Schellevis committed
954 955 956 957

	return $retval;
}

958 959
function system_webgui_start()
{
960
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
961

962
	chdir('/usr/local/www');
Ad Schellevis's avatar
Ad Schellevis committed
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987

	/* defaults */
	$portarg = "80";
	$crt = "";
	$key = "";
	$ca = "";

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

	if ($config['system']['webgui']['protocol'] == "https") {
		// Ensure that we have a webConfigurator CERT
		$cert =& lookup_cert($config['system']['webgui']['ssl-certref']);
		if(!is_array($cert) && !$cert['crt'] && !$cert['prv']) {
			if (!is_array($config['ca']))
				$config['ca'] = array();
			$a_ca =& $config['ca'];
			if (!is_array($config['cert']))
				$config['cert'] = array();
			$a_cert =& $config['cert'];
			log_error("Creating SSL Certificate for this host");
			$cert = array();
			$cert['refid'] = uniqid();
			$cert['descr'] = gettext("webConfigurator default");
988 989 990 991 992 993 994
			mwexec(
				/* XXX ought to be replaced by PHP calls */
				'/usr/local/bin/openssl req -new ' .
				'-newkey rsa:4096 -sha256 -days 365 -nodes -x509 ' .
				'-subj "/C=NL/ST=Zuid-Holland/L=Middelharnis/O=OPNsense" ' .
				'-keyout /tmp/ssl.key -out /tmp/ssl.crt'
			);
995 996 997 998
			$crt = file_get_contents('/tmp/ssl.crt');
			$key = file_get_contents('/tmp/ssl.key');
			unlink('/tmp/ssl.key');
			unlink('/tmp/ssl.crt');
Ad Schellevis's avatar
Ad Schellevis committed
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
			cert_import($cert, $crt, $key);
			$a_cert[] = $cert;
			$config['system']['webgui']['ssl-certref'] = $cert['refid'];
			write_config(gettext("Importing HTTPS certificate"));
			if(!$config['system']['webgui']['port'])
				$portarg = "443";
			$ca = ca_chain($cert);
		} else {
			$crt = base64_decode($cert['crt']);
			$key = base64_decode($cert['prv']);
			if(!$config['system']['webgui']['port'])
				$portarg = "443";
			$ca = ca_chain($cert);
		}
	}

	/* generate lighttpd configuration */
1016
	system_generate_lighty_config("/var/etc/lighty-webConfigurator.conf",
Ad Schellevis's avatar
Ad Schellevis committed
1017 1018 1019 1020
		$crt, $key, $ca, "lighty-webConfigurator.pid", $portarg, "/usr/local/www/",
		"cert.pem", "ca.pem");

	/* kill any running lighttpd */
1021
	killbypid('/var/run/lighty-webConfigurator.pid');
Ad Schellevis's avatar
Ad Schellevis committed
1022 1023 1024

	sleep(1);

1025 1026 1027
	/* regenerate the php.ini files in case the setup has changed */
	mwexec('/usr/local/etc/rc.php_ini_setup');

1028
	/* attempt to start lighthttpd and return true if ok */
1029
	return !mwexec("/usr/local/sbin/lighttpd -f /var/etc/lighty-webConfigurator.conf");
Ad Schellevis's avatar
Ad Schellevis committed
1030 1031
}

1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
/*
 *     get_memory()
 *     returns an array listing the amount of
 *     memory installed in the hardware
 *     [0] net memory available for the OS (FreeBSD) after some is taken by BIOS, video or whatever - e.g. 235 MBytes
 *     [1] real (actual) memory of the system, should be the size of the RAM card/s - e.g. 256 MBytes
 */
function get_memory() {
	$physmem = get_single_sysctl("hw.physmem");
	$realmem = get_single_sysctl("hw.realmem");
	/* convert from bytes to megabytes */
	return array(($physmem/1048576),($realmem/1048576));
}


1047 1048
function system_generate_lighty_config(
	$filename,
Ad Schellevis's avatar
Ad Schellevis committed
1049 1050 1051 1052 1053
	$cert,
	$key,
	$ca,
	$pid_file,
	$port = 80,
1054 1055
	$document_root = '/usr/local/www/',
	$cert_location = 'cert.pem',
1056
	$ca_location = 'ca.pem')
1057
{
Franco Fichtner's avatar
Franco Fichtner committed
1058
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
1059

1060
	@mkdir('/tmp/lighttpdcompress');
Ad Schellevis's avatar
Ad Schellevis committed
1061

1062
	$http_rewrite_rules = <<<EOD
1063
# Phalcon ui and api routing
1064 1065 1066 1067 1068
alias.url += ( "/ui/" => "/usr/local/opnsense/www/" )
alias.url += ( "/api/"  => "/usr/local/opnsense/www/" )
url.rewrite-if-not-file = ( "^/ui/(.*)$" => "/ui/index.php?_url=/$1" ,
                            "^/api/(.*)$" => "/api/api.php?_url=/$1"
)
1069 1070

EOD;
1071 1072 1073
	$server_upload_dirs = "server.upload-dirs = ( \"/root/\", \"/tmp/\", \"/var/\" )\n";
	$server_max_request_size = "server.max-request-size    = 2097152";
	$cgi_config = "cgi.assign                 = ( \".cgi\" => \"\" )";
1074

Ad Schellevis's avatar
Ad Schellevis committed
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
	if (empty($port))
		$lighty_port = "80";
	else
		$lighty_port = $port;

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

1087
	$fast_cgi_path = "/tmp/php-fastcgi.socket";
Ad Schellevis's avatar
Ad Schellevis committed
1088

1089
	$fastcgi_config = <<<EOD
Ad Schellevis's avatar
Ad Schellevis committed
1090 1091 1092 1093 1094 1095
#### fastcgi module
## read fastcgi.txt for more info
fastcgi.server = ( ".php" =>
	( "localhost" =>
		(
			"socket" => "{$fast_cgi_path}",
1096
			"max-procs" => 2,
Ad Schellevis's avatar
Ad Schellevis committed
1097
			"bin-environment" => (
1098
				"PHP_FCGI_CHILDREN" => "3",
1099
				"PHP_FCGI_MAX_REQUESTS" => "100"
Ad Schellevis's avatar
Ad Schellevis committed
1100
			),
1101
			"bin-path" => "/usr/local/bin/php-cgi"
Ad Schellevis's avatar
Ad Schellevis committed
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
		)
	)
)

EOD;

	$lighty_config = <<<EOD
#
# lighttpd configuration file
#
# use a it as base for lighttpd 1.0.0 and above
#
############ Options you really have to take care of ####################

## FreeBSD!
server.event-handler	= "freebsd-kqueue"
1118
server.network-backend	= "writev"
Ad Schellevis's avatar
Ad Schellevis committed
1119 1120 1121 1122
#server.use-ipv6 = "enable"

## modules to load
server.modules              =   ( "mod_access", "mod_expire", "mod_compress", "mod_redirect",
1123
	"mod_cgi", "mod_fastcgi","mod_alias", "mod_rewrite"
Ad Schellevis's avatar
Ad Schellevis committed
1124 1125 1126 1127 1128 1129 1130 1131
)

server.max-keep-alive-requests = 15
server.max-keep-alive-idle = 30

## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
server.document-root        = "{$document_root}"
1132 1133


1134
{$http_rewrite_rules}
Ad Schellevis's avatar
Ad Schellevis committed
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170

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

{$lighty_use_syslog}

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

# mimetype mapping
mimetype.assign             = (
  ".pdf"          =>      "application/pdf",
  ".sig"          =>      "application/pgp-signature",
  ".spl"          =>      "application/futuresplash",
  ".class"        =>      "application/octet-stream",
  ".ps"           =>      "application/postscript",
  ".torrent"      =>      "application/x-bittorrent",
  ".dvi"          =>      "application/x-dvi",
  ".gz"           =>      "application/x-gzip",
  ".pac"          =>      "application/x-ns-proxy-autoconfig",
  ".swf"          =>      "application/x-shockwave-flash",
  ".tar.gz"       =>      "application/x-tgz",
  ".tgz"          =>      "application/x-tgz",
  ".tar"          =>      "application/x-tar",
  ".zip"          =>      "application/zip",
  ".mp3"          =>      "audio/mpeg",
  ".m3u"          =>      "audio/x-mpegurl",
  ".wma"          =>      "audio/x-ms-wma",
  ".wax"          =>      "audio/x-ms-wax",
  ".ogg"          =>      "audio/x-wav",
  ".wav"          =>      "audio/x-wav",
  ".gif"          =>      "image/gif",
  ".jpg"          =>      "image/jpeg",
  ".jpeg"         =>      "image/jpeg",
  ".png"          =>      "image/png",
1171
  ".svg"          =>      "image/svg+xml",
Ad Schellevis's avatar
Ad Schellevis committed
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
  ".xbm"          =>      "image/x-xbitmap",
  ".xpm"          =>      "image/x-xpixmap",
  ".xwd"          =>      "image/x-xwindowdump",
  ".css"          =>      "text/css",
  ".html"         =>      "text/html",
  ".htm"          =>      "text/html",
  ".js"           =>      "text/javascript",
  ".asc"          =>      "text/plain",
  ".c"            =>      "text/plain",
  ".conf"         =>      "text/plain",
  ".text"         =>      "text/plain",
  ".txt"          =>      "text/plain",
  ".dtd"          =>      "text/xml",
  ".xml"          =>      "text/xml",
  ".mpeg"         =>      "video/mpeg",
  ".mpg"          =>      "video/mpeg",
  ".mov"          =>      "video/quicktime",
  ".qt"           =>      "video/quicktime",
  ".avi"          =>      "video/x-msvideo",
  ".asf"          =>      "video/x-ms-asf",
  ".asx"          =>      "video/x-ms-asf",
  ".wmv"          =>      "video/x-ms-wmv",
  ".bz2"          =>      "application/x-bzip",
  ".tbz"          =>      "application/x-bzip-compressed-tar",
  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
 )

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

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


######### Options that are good to be but not neccesary to be changed #######

## bind to port (default: 80)

EOD;

	$lighty_config .= "server.bind  = \"0.0.0.0\"\n";
	$lighty_config .= "server.port  = {$lighty_port}\n";
	$lighty_config .= "\$SERVER[\"socket\"]  == \"0.0.0.0:{$lighty_port}\" { }\n";
	$lighty_config .= "\$SERVER[\"socket\"]  == \"[::]:{$lighty_port}\" { \n";
	if($cert <> "" and $key <> "") {
		$lighty_config .= "\n";
		$lighty_config .= "## ssl configuration\n";
		$lighty_config .= "ssl.engine = \"enable\"\n";
1224
		$lighty_config .= "ssl.pemfile = \"/var/etc/{$cert_location}\"\n\n";
Ad Schellevis's avatar
Ad Schellevis committed
1225
		if($ca <> "")
1226
			$lighty_config .= "ssl.ca-file = \"/var/etc/{$ca_location}\"\n\n";
Ad Schellevis's avatar
Ad Schellevis committed
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
	}
	$lighty_config .= " }\n";


	$lighty_config .= <<<EOD

## error-handler for status 404
#server.error-handler-404   = "/error-handler.html"
#server.error-handler-404   = "/error-handler.php"

## to help the rc.scripts
1238
server.pid-file            = "/var/run/{$pid_file}"
Ad Schellevis's avatar
Ad Schellevis committed
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249

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

## enable debugging
debug.log-request-header   = "disable"
debug.log-response-header  = "disable"
debug.log-request-handling = "disable"
debug.log-file-not-found   = "disable"

# gzip compression
1250
compress.cache-dir = "/tmp/lighttpdcompress/"
Ad Schellevis's avatar
Ad Schellevis committed
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
compress.filetype  = ("text/plain","text/css", "text/xml", "text/javascript" )

{$server_upload_dirs}

{$server_max_request_size}

{$fastcgi_config}

{$cgi_config}

expire.url = (
1262
				"" => "access 50 hours",
Ad Schellevis's avatar
Ad Schellevis committed
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
        )

EOD;

	$cert = str_replace("\r", "", $cert);
	$key = str_replace("\r", "", $key);
	$ca = str_replace("\r", "", $ca);

	$cert = str_replace("\n\n", "\n", $cert);
	$key = str_replace("\n\n", "\n", $key);
	$ca = str_replace("\n\n", "\n", $ca);

	if($cert <> "" and $key <> "") {
1276
		$fd = fopen("/var/etc/{$cert_location}", "w");
Ad Schellevis's avatar
Ad Schellevis committed
1277 1278 1279 1280
		if (!$fd) {
			printf(gettext("Error: cannot open cert.pem in system_webgui_start().%s"), "\n");
			return 1;
		}
1281
		chmod("/var/etc/{$cert_location}", 0600);
Ad Schellevis's avatar
Ad Schellevis committed
1282 1283 1284 1285 1286
		fwrite($fd, $cert);
		fwrite($fd, "\n");
		fwrite($fd, $key);
		fclose($fd);
		if(!(empty($ca) || (strlen(trim($ca)) == 0))) {
1287
			$fd = fopen("/var/etc/{$ca_location}", "w");
Ad Schellevis's avatar
Ad Schellevis committed
1288 1289 1290 1291
			if (!$fd) {
				printf(gettext("Error: cannot open ca.pem in system_webgui_start().%s"), "\n");
				return 1;
			}
1292
			chmod("/var/etc/{$ca_location}", 0600);
Ad Schellevis's avatar
Ad Schellevis committed
1293 1294 1295 1296 1297 1298
			fwrite($fd, $ca);
			fclose($fd);
		}
		$lighty_config .= "\n";
		$lighty_config .= "## " . gettext("ssl configuration") . "\n";
		$lighty_config .= "ssl.engine = \"enable\"\n";
1299
		$lighty_config .= "ssl.pemfile = \"/var/etc/{$cert_location}\"\n\n";
Ad Schellevis's avatar
Ad Schellevis committed
1300 1301 1302 1303

		// Harden SSL a bit for PCI conformance testing
		$lighty_config .= "ssl.use-sslv2 = \"disable\"\n";

1304
		$lighty_config .= 'ssl.cipher-list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"' . PHP_EOL;
Ad Schellevis's avatar
Ad Schellevis committed
1305 1306

		if(!(empty($ca) || (strlen(trim($ca)) == 0)))
1307
			$lighty_config .= "ssl.ca-file = \"/var/etc/{$ca_location}\"\n\n";
Ad Schellevis's avatar
Ad Schellevis committed
1308 1309
	}

1310
	// Add HTTP to HTTPS redirect
1311
	if ($config['system']['webgui']['protocol'] == "https" && !isset($config['system']['webgui']['disablehttpredirect'])) {
1312
		if($lighty_port != "443") {
Ad Schellevis's avatar
Ad Schellevis committed
1313
			$redirectport = ":{$lighty_port}";
1314 1315 1316
		} else {
			$redirectport = "";
		}
Ad Schellevis's avatar
Ad Schellevis committed
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
		$lighty_config .= <<<EOD
\$SERVER["socket"] == ":80" {
	\$HTTP["host"] =~ "(.*)" {
		url.redirect = ( "^/(.*)" => "https://%1{$redirectport}/$1" )
	}
}
\$SERVER["socket"] == "[::]:80" {
	\$HTTP["host"] =~ "(.*)" {
		url.redirect = ( "^/(.*)" => "https://%1{$redirectport}/$1" )
	}
}
EOD;
	}

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

	return 0;

}

1343 1344 1345 1346
function system_firmware_configure()
{
	global $config;

1347 1348 1349
	/* our own ABI prefix on the mirror */
	$osabi = '15.7';

1350 1351 1352 1353 1354
	/* rewrite the config via the defaults */
	$origin_conf = '/usr/local/etc/pkg/repos/origin.conf';
	copy("${origin_conf}.sample", $origin_conf);

	if (isset($config['system']['firmware']['mirror'])) {
1355 1356 1357
		configd_run('firmware mirror ' . escapeshellarg(
			str_replace('/', '\/', $config['system']['firmware']['mirror'])
		));
1358 1359 1360
	}

	if (isset($config['system']['firmware']['flavour'])) {
1361 1362 1363
		configd_run('firmware flavour ' . escapeshellarg(
			str_replace('/', '\/', $osabi . '/' . $config['system']['firmware']['flavour'])
		));
1364 1365 1366
	}
}

1367 1368
function system_timezone_configure()
{
Franco Fichtner's avatar
Franco Fichtner committed
1369
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
1370 1371 1372

	$syscfg = $config['system'];

Ad Schellevis's avatar
Ad Schellevis committed
1373
	if (file_exists("/var/run/booting"))
Ad Schellevis's avatar
Ad Schellevis committed
1374 1375 1376 1377
		echo gettext("Setting timezone...");

	/* extract appropriate timezone file */
	$timezone = $syscfg['timezone'];
1378
	$timezones = get_zoneinfo();
Ad Schellevis's avatar
Ad Schellevis committed
1379

1380 1381 1382 1383
	// Reset to default if empty or not existend
	if (empty($timezone) || !in_array($timezone, $timezones)) {
		$timezone = 'Etc/UTC';
	}
Ad Schellevis's avatar
Ad Schellevis committed
1384

1385 1386
	// Apply timezone
	copy(sprintf('/usr/share/zoneinfo/%s', $timezone), '/etc/localtime');
Ad Schellevis's avatar
Ad Schellevis committed
1387 1388 1389

	mwexec("sync");

Ad Schellevis's avatar
Ad Schellevis committed
1390
	if (file_exists("/var/run/booting"))
Ad Schellevis's avatar
Ad Schellevis committed
1391 1392 1393
		echo gettext("done.") . "\n";
}

Franco Fichtner's avatar
Franco Fichtner committed
1394 1395 1396
function system_ntp_setup_gps($serialport)
{
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
1397 1398 1399 1400 1401 1402 1403
	$gps_device = '/dev/gps0';
	$serialport = '/dev/'.$serialport;

	if (!file_exists($serialport))
		return false;

	// Create symlink that ntpd requires
1404
	@unlink($gps_device);
Ad Schellevis's avatar
Ad Schellevis committed
1405 1406 1407
	symlink($serialport, $gps_device);

	/* Send the following to the GPS port to initialize the GPS */
1408
	if (isset($config['ntpd']['gps'])) {
Ad Schellevis's avatar
Ad Schellevis committed
1409
		$gps_init = base64_decode($config['ntpd']['gps']['initcmd']);
1410
	} else {
Ad Schellevis's avatar
Ad Schellevis committed
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
		$gps_init = base64_decode('JFBVQlgsNDAsR1NWLDAsMCwwLDAqNTkNCiRQVUJYLDQwLEdMTCwwLDAsMCwwKjVDDQokUFVCWCw0MCxaREEsMCwwLDAsMCo0NA0KJFBVQlgsNDAsVlRHLDAsMCwwLDAqNUUNCiRQVUJYLDQwLEdTViwwLDAsMCwwKjU5DQokUFVCWCw0MCxHU0EsMCwwLDAsMCo0RQ0KJFBVQlgsNDAsR0dBLDAsMCwwLDANCiRQVUJYLDQwLFRYVCwwLDAsMCwwDQokUFVCWCw0MCxSTUMsMCwwLDAsMCo0Ng0KJFBVQlgsNDEsMSwwMDA3LDAwMDMsNDgwMCwwDQokUFVCWCw0MCxaREEsMSwxLDEsMQ==');
	}

	/* XXX: Why not file_put_contents to the device */
	@file_put_contents('/tmp/gps.init', $gps_init);
	`cat /tmp/gps.init > $serialport`;

	/* Add /etc/remote entry in case we need to read from the GPS with tip */
	if (intval(`grep -c '^gps0' /etc/remote`) == 0) {
		$gpsbaud = '4800';
		if (is_array($config['ntpd']) && is_array($config['ntpd']['gps']) && !empty($config['ntpd']['gps']['speed'])) {
			switch($config['ntpd']['gps']['speed']) {
				case '16':
					$gpsbaud = '9600';
					break;
				case '32':
					$gpsbaud = '19200';
					break;
				case '48':
					$gpsbaud = '38400';
					break;
				case '64':
					$gpsbaud = '57600';
					break;
				case '80':
					$gpsbaud = '115200';
					break;
			}
		}
		@file_put_contents("/etc/remote", "gps0:dv={$serialport}:br#{$gpsbaud}:pa=none:", FILE_APPEND);
	}

	return true;
}

1446 1447
function system_ntp_setup_pps($serialport)
{
Ad Schellevis's avatar
Ad Schellevis committed
1448
	$pps_device = '/dev/pps0';
1449
	$serialport = "/dev/{$serialport}";
Ad Schellevis's avatar
Ad Schellevis committed
1450

1451
	if (!file_exists($serialport)) {
Ad Schellevis's avatar
Ad Schellevis committed
1452
		return false;
1453
	}
Ad Schellevis's avatar
Ad Schellevis committed
1454 1455

	// Create symlink that ntpd requires
1456
	@unlink($pps_device);
Ad Schellevis's avatar
Ad Schellevis committed
1457 1458 1459 1460 1461
	@symlink($serialport, $pps_device);

	return true;
}

1462 1463
function system_ntp_configure($start_ntpd = true)
{
Franco Fichtner's avatar
Franco Fichtner committed
1464
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
1465

1466 1467
	$driftfile = '/var/db/ntpd.drift';
	$statsdir = '/var/log/ntp';
Ad Schellevis's avatar
Ad Schellevis committed
1468 1469
	$gps_device = '/dev/gps0';

1470
	@mkdir($statsdir, 0755);
Ad Schellevis's avatar
Ad Schellevis committed
1471

1472
	if (!isset($config['ntpd']) || !is_array($config['ntpd'])) {
Ad Schellevis's avatar
Ad Schellevis committed
1473
		$config['ntpd'] = array();
1474
	}
Ad Schellevis's avatar
Ad Schellevis committed
1475 1476

	$ntpcfg = "# \n";
Ad Schellevis's avatar
Ad Schellevis committed
1477
	$ntpcfg .= "# OPNsense ntp configuration file \n";
Ad Schellevis's avatar
Ad Schellevis committed
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
	$ntpcfg .= "# \n\n";
	$ntpcfg .= "tinker panic 0 \n";

	/* Add Orphan mode */
	$ntpcfg .= "# Orphan mode stratum\n";
	$ntpcfg .= 'tos orphan ';
	if (!empty($config['ntpd']['orphan'])) {
		$ntpcfg .= $config['ntpd']['orphan'];
	}else{
		$ntpcfg .= '12';
	}
	$ntpcfg .= "\n";

	/* Add PPS configuration */
	if (!empty($config['ntpd']['pps'])
		&& file_exists('/dev/'.$config['ntpd']['pps']['port'])
		&& system_ntp_setup_pps($config['ntpd']['pps']['port'])) {
		$ntpcfg .= "\n";
		$ntpcfg .= "# PPS Setup\n";
		$ntpcfg .= 'server 127.127.22.0';
		$ntpcfg .= ' minpoll 4 maxpoll 4';
		if (empty($config['ntpd']['pps']['prefer'])) { /*note: this one works backwards */
1500
			$ntpcfg .= ' prefer';
Ad Schellevis's avatar
Ad Schellevis committed
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
		}
		if (!empty($config['ntpd']['pps']['noselect'])) {
			$ntpcfg .= ' noselect ';
		}
		$ntpcfg .= "\n";
		$ntpcfg .= 'fudge 127.127.22.0';
		if (!empty($config['ntpd']['pps']['fudge1'])) {
			$ntpcfg .= ' time1 ';
			$ntpcfg .= $config['ntpd']['pps']['fudge1'];
		}
		if (!empty($config['ntpd']['pps']['flag2'])) {
			$ntpcfg .= ' flag2 1';
		}
		if (!empty($config['ntpd']['pps']['flag3'])) {
			$ntpcfg .= ' flag3 1';
		}else{
			$ntpcfg .= ' flag3 0';
		}
		if (!empty($config['ntpd']['pps']['flag4'])) {
			$ntpcfg .= ' flag4 1';
		}
		if (!empty($config['ntpd']['pps']['refid'])) {
			$ntpcfg .= ' refid ';
			$ntpcfg .= $config['ntpd']['pps']['refid'];
		}
		$ntpcfg .= "\n";
	}
	/* End PPS configuration */

	/* Add GPS configuration */
1531
        if (isset($config['ntpd']['gps']['port'])
Ad Schellevis's avatar
Ad Schellevis committed
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
		&& file_exists('/dev/'.$config['ntpd']['gps']['port'])
		&& system_ntp_setup_gps($config['ntpd']['gps']['port'])) {
		$ntpcfg .= "\n";
		$ntpcfg .= "# GPS Setup\n";
		$ntpcfg .= 'server 127.127.20.0 mode ';
		if (!empty($config['ntpd']['gps']['nmea']) || !empty($config['ntpd']['gps']['speed']) || !empty($config['ntpd']['gps']['subsec'])) {
			if (!empty($config['ntpd']['gps']['nmea'])) {
				$ntpmode = (int) $config['ntpd']['gps']['nmea'];
			}
			if (!empty($config['ntpd']['gps']['speed'])) {
				$ntpmode += (int) $config['ntpd']['gps']['speed'];
			}
			if (!empty($config['ntpd']['gps']['subsec'])) {
				$ntpmode += 128;
			}
			$ntpcfg .= (string) $ntpmode;
		}else{
			$ntpcfg .= '0';
		}
		$ntpcfg .= ' minpoll 4 maxpoll 4';
		if (empty($config['ntpd']['gps']['prefer'])) { /*note: this one works backwards */
1553
			$ntpcfg .= ' prefer';
Ad Schellevis's avatar
Ad Schellevis committed
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
		}
		if (!empty($config['ntpd']['gps']['noselect'])) {
			$ntpcfg .= ' noselect ';
		}
		$ntpcfg .= "\n";
		$ntpcfg .= 'fudge 127.127.20.0';
		if (!empty($config['ntpd']['gps']['fudge1'])) {
			$ntpcfg .= ' time1 ';
			$ntpcfg .= $config['ntpd']['gps']['fudge1'];
		}
		if (!empty($config['ntpd']['gps']['fudge2'])) {
			$ntpcfg .= ' time2 ';
			$ntpcfg .= $config['ntpd']['gps']['fudge2'];
		}
		if (!empty($config['ntpd']['gps']['flag1'])) {
			$ntpcfg .= ' flag1 1';
		}else{
			$ntpcfg .= ' flag1 0';
		}
		if (!empty($config['ntpd']['gps']['flag2'])) {
			$ntpcfg .= ' flag2 1';
		}
		if (!empty($config['ntpd']['gps']['flag3'])) {
			$ntpcfg .= ' flag3 1';
		}else{
			$ntpcfg .= ' flag3 0';
		}
		if (!empty($config['ntpd']['gps']['flag4'])) {
			$ntpcfg .= ' flag4 1';
		}
		if (!empty($config['ntpd']['gps']['refid'])) {
			$ntpcfg .= ' refid ';
			$ntpcfg .= $config['ntpd']['gps']['refid'];
		}
		$ntpcfg .= "\n";
	}
	/* End GPS configuration */
1591

Ad Schellevis's avatar
Ad Schellevis committed
1592 1593 1594 1595
	$ntpcfg .= "\n\n# Upstream Servers\n";
	/* foreach through ntp servers and write out to ntpd.conf */
	foreach (explode(' ', $config['system']['timeservers']) as $ts) {
		$ntpcfg .= "server {$ts} iburst maxpoll 9";
1596 1597
		if (isset($config['ntpd']['prefer']) && substr_count($config['ntpd']['prefer'], $ts)) $ntpcfg .= ' prefer';
		if (isset($config['ntpd']['noselect']) && substr_count($config['ntpd']['noselect'], $ts)) $ntpcfg .= ' noselect';
Ad Schellevis's avatar
Ad Schellevis committed
1598 1599 1600 1601 1602
		$ntpcfg .= "\n";
	}
	unset($ts);

	$ntpcfg .= "\n\n";
1603
	$ntpcfg .= "disable monitor\n"; //prevent NTP reflection attack, see https://ics-cert.us-cert.gov/advisories/ICSA-14-051-04
Ad Schellevis's avatar
Ad Schellevis committed
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630
	if (!empty($config['ntpd']['clockstats']) || !empty($config['ntpd']['loopstats']) || !empty($config['ntpd']['peerstats'])) {
		$ntpcfg .= "enable stats\n";
		$ntpcfg .= 'statistics';
		if (!empty($config['ntpd']['clockstats'])) {
			$ntpcfg .= ' clockstats';
		}
		if (!empty($config['ntpd']['loopstats'])) {
			$ntpcfg .= ' loopstats';
		}
		if (!empty($config['ntpd']['peerstats'])) {
			$ntpcfg .= ' peerstats';
		}
		$ntpcfg .= "\n";
	}
	$ntpcfg .= "statsdir {$statsdir}\n";
	$ntpcfg .= 'logconfig =syncall +clockall';
	if (!empty($config['ntpd']['logpeer'])) {
		$ntpcfg .= ' +peerall';
	}
	if (!empty($config['ntpd']['logsys'])) {
		$ntpcfg .= ' +sysall';
	}
	$ntpcfg .= "\n";
	$ntpcfg .= "driftfile {$driftfile}\n";
	/* Access restrictions */
	$ntpcfg .= 'restrict default';
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1631
		$ntpcfg .= ' kod limited';
Ad Schellevis's avatar
Ad Schellevis committed
1632 1633
	}
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1634
		$ntpcfg .= ' nomodify';
Ad Schellevis's avatar
Ad Schellevis committed
1635 1636 1637 1638 1639
	}
	if (!empty($config['ntpd']['noquery'])) {
		$ntpcfg .= ' noquery';
	}
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1640
		$ntpcfg .= ' nopeer';
Ad Schellevis's avatar
Ad Schellevis committed
1641 1642
	}
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1643
		$ntpcfg .= ' notrap';
Ad Schellevis's avatar
Ad Schellevis committed
1644 1645 1646 1647 1648 1649
	}
	if (!empty($config['ntpd']['noserve'])) {
		$ntpcfg .= ' noserve';
	}
	$ntpcfg .= "\nrestrict -6 default";
	if (empty($config['ntpd']['kod'])) { /*note: this one works backwards */
1650
		$ntpcfg .= ' kod limited';
Ad Schellevis's avatar
Ad Schellevis committed
1651 1652
	}
	if (empty($config['ntpd']['nomodify'])) { /*note: this one works backwards */
1653
		$ntpcfg .= ' nomodify';
Ad Schellevis's avatar
Ad Schellevis committed
1654 1655 1656 1657 1658
	}
	if (!empty($config['ntpd']['noquery'])) {
		$ntpcfg .= ' noquery';
	}
	if (empty($config['ntpd']['nopeer'])) { /*note: this one works backwards */
1659
		$ntpcfg .= ' nopeer';
Ad Schellevis's avatar
Ad Schellevis committed
1660 1661 1662 1663 1664
	}
	if (!empty($config['ntpd']['noserve'])) {
		$ntpcfg .= ' noserve';
	}
	if (empty($config['ntpd']['notrap'])) { /*note: this one works backwards */
1665
		$ntpcfg .= ' notrap';
Ad Schellevis's avatar
Ad Schellevis committed
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
	}
	$ntpcfg .= "\n";

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

Ad Schellevis's avatar
Ad Schellevis committed
1677

1678 1679 1680 1681
	$interfaces = array();
	if (isset($config['ntpd']['interface'])) {
		$interfaces = explode(',', $config['ntpd']['interface']);
	}
Ad Schellevis's avatar
Ad Schellevis committed
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694

	if (is_array($interfaces) && count($interfaces)) {
		$ntpcfg .= "interface ignore all\n";
		foreach ($interfaces as $interface) {
			if (!is_ipaddr($interface)) {
				$interface = get_real_interface($interface);
			}
			if (!empty($interface))
				$ntpcfg .= "interface listen {$interface}\n";
		}
	}

	/* open configuration for wrting or bail */
1695 1696
	if (!@file_put_contents('/var/etc/ntpd.conf', $ntpcfg)) {
		log_error("Could not open /var/etc/ntpd.conf for writing");
Ad Schellevis's avatar
Ad Schellevis committed
1697 1698 1699
		return;
	}

1700 1701 1702
	if (!$start_ntpd) {
		/* write out the config and delay startup */
		mwexec_bg('/usr/local/sbin/ntpdate_sync_once.sh');
Ad Schellevis's avatar
Ad Schellevis committed
1703
		return;
1704
	}
Ad Schellevis's avatar
Ad Schellevis committed
1705 1706

	/* if ntpd is running, kill it */
1707 1708 1709
	while (isvalidpid('/var/run/ntpd.pid')) {
		killbypid('/var/run/ntpd.pid');
		usleep(200 * 1000);
Ad Schellevis's avatar
Ad Schellevis committed
1710 1711 1712
	}

	/* if /var/empty does not exist, create it */
1713
	@mkdir('/var/empty', 0775, true);
Ad Schellevis's avatar
Ad Schellevis committed
1714

1715 1716 1717 1718 1719
	/* start opentpd, set time now and use new config */
	mwexecf(
		'/usr/local/sbin/ntpd -g -c %s -p %s',
		array('/var/etc/ntpd.conf', '/var/run/ntpd.pid')
	);
1720

Ad Schellevis's avatar
Ad Schellevis committed
1721 1722 1723 1724
	// Note that we are starting up
	log_error("NTPD is starting up.");
}

1725
function system_halt($sync = false)
1726
{
1727
	$cmd ='/usr/local/etc/rc.halt';
Ad Schellevis's avatar
Ad Schellevis committed
1728

1729
	if (!$sync) {
1730 1731 1732
		mwexec_bg($cmd);
	} else {
		mwexec($cmd);
1733
	}
Ad Schellevis's avatar
Ad Schellevis committed
1734 1735
}

1736 1737
function system_reboot($sync = false)
{
1738
	$cmd ='/usr/local/etc/rc.reboot';
1739 1740

	if (!$sync) {
1741 1742 1743
		mwexec_bg($cmd);
	} else {
		mwexec($cmd);
1744
	}
Ad Schellevis's avatar
Ad Schellevis committed
1745 1746
}

1747 1748 1749 1750 1751
function system_console_configure()
{
	setup_serial_port();
}

1752 1753
function system_set_harddisk_standby()
{
Franco Fichtner's avatar
Franco Fichtner committed
1754
	global $config;
Ad Schellevis's avatar
Ad Schellevis committed
1755 1756

	if (isset($config['system']['harddiskstandby'])) {
Ad Schellevis's avatar
Ad Schellevis committed
1757
		if (file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
1758 1759 1760 1761 1762 1763
			echo gettext('Setting hard disk standby... ');
		}

		$standby = $config['system']['harddiskstandby'];
		// Check for a numeric value
		if (is_numeric($standby)) {
1764
			mwexec('/bin/sync');
Ad Schellevis's avatar
Ad Schellevis committed
1765 1766 1767
			if (set_single_sysctl('hw.ata.standby', (int)$standby)) {
				// Reinitialize ATA-drives
				mwexec('/usr/local/sbin/atareinit');
Ad Schellevis's avatar
Ad Schellevis committed
1768
				if (file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
1769 1770
					echo gettext("done.") . "\n";
				}
Ad Schellevis's avatar
Ad Schellevis committed
1771
			} else if (file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
1772 1773
				echo gettext("failed!") . "\n";
			}
Ad Schellevis's avatar
Ad Schellevis committed
1774
		} else if (file_exists("/var/run/booting")) {
Ad Schellevis's avatar
Ad Schellevis committed
1775 1776 1777 1778 1779
			echo gettext("failed!") . "\n";
		}
	}
}

1780 1781
function system_setup_sysctl()
{
Ad Schellevis's avatar
Ad Schellevis committed
1782 1783
	global $config;

1784
	activate_sysctls();
Ad Schellevis's avatar
Ad Schellevis committed
1785 1786 1787 1788 1789 1790

	if (isset($config['system']['sharednet'])) {
		system_disable_arp_wrong_if();
	}
}

1791 1792
function system_disable_arp_wrong_if()
{
Ad Schellevis's avatar
Ad Schellevis committed
1793
	global $config;
1794

Ad Schellevis's avatar
Ad Schellevis committed
1795 1796 1797 1798 1799 1800
	set_sysctl(array(
		"net.link.ether.inet.log_arp_wrong_iface" => "0",
		"net.link.ether.inet.log_arp_movements" => "0"
	));
}

1801 1802
function enable_watchdog()
{
Ad Schellevis's avatar
Ad Schellevis committed
1803
	global $config;
1804 1805 1806

	return;	/* XXX delete or repair please */

Ad Schellevis's avatar
Ad Schellevis committed
1807 1808
	$install_watchdog = false;
	$supported_watchdogs = array("Geode");
1809
	$file = @file_get_contents('/var/run/dmesg.boot');
Ad Schellevis's avatar
Ad Schellevis committed
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
	foreach($supported_watchdogs as $sd) {
		if(stristr($file, "Geode")) {
			$install_watchdog = true;
		}
	}
	if($install_watchdog == true) {
		if(is_process_running("watchdogd"))
			mwexec("/usr/bin/killall watchdogd", true);
		exec("/usr/sbin/watchdogd");
	}
}



function get_possible_listen_ips($include_ipv6_link_local=false) {
	$interfaces = get_configured_interface_with_descr();
	$carplist = get_configured_carp_interface_list();
	$listenips = array();
	foreach ($carplist as $cif => $carpip)
		$interfaces[$cif] = $carpip." (".get_vip_descr($carpip).")";
	$aliaslist = get_configured_ip_aliases_list();
	foreach ($aliaslist as $aliasip => $aliasif)
		$interfaces[$aliasip] = $aliasip." (".get_vip_descr($aliasip).")";
	foreach ($interfaces as $iface => $ifacename) {
		$tmp["name"]  = $ifacename;
		$tmp["value"] = $iface;
		$listenips[] = $tmp;
		if ($include_ipv6_link_local) {
			$llip = find_interface_ipv6_ll(get_real_interface($iface));
			if (!empty($llip)) {
				$tmp["name"]  = "{$ifacename} IPv6 Link-Local";
				$tmp["value"] = $llip;
				$listenips[] = $tmp;
			}
		}
	}
	$tmp["name"]  = "Localhost";
	$tmp["value"] = "lo0";
	$listenips[] = $tmp;
	return $listenips;
}

function get_possible_traffic_source_addresses($include_ipv6_link_local=false) {
	global $config;
	$sourceips = get_possible_listen_ips($include_ipv6_link_local);
	foreach (array('server', 'client') as $mode) {
1856
		if (isset($config['openvpn']["openvpn-{$mode}"]) && is_array($config['openvpn']["openvpn-{$mode}"])) {
Ad Schellevis's avatar
Ad Schellevis committed
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868
			foreach ($config['openvpn']["openvpn-{$mode}"] as $id => $setting) {
				if (!isset($setting['disable'])) {
					$vpn = array();
					$vpn['value'] = 'ovpn' . substr($mode, 0, 1) . $setting['vpnid'];
					$vpn['name'] = gettext("OpenVPN") . " ".$mode.": ".htmlspecialchars($setting['description']);
					$sourceips[] = $vpn;
				}
			}
		}
	}
	return $sourceips;
}