Projet

Général

Profil

Télécharger (22,6 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / unbound.inc @ 340ce958

1
<?php
2
/*
3
	unbound.inc
4
	part of the pfSense project (https://www.pfsense.org)
5
	Copyright (C) 2014 Warren Baker <warren@decoy.co.za>
6
	All rights reserved.
7

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

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

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

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

    
29
	pfSense_BUILDER_BINARIES:   /usr/sbin/unbound  /usr/sbin/unbound-anchor    /usr/sbin/unbound-checkconf
30
	pfSense_BUILDER_BINARIES:   /usr/sbin/unbound-control    /usr/sbin/unbound-control-setup
31
	pfSense_MODULE: unbound
32
*/
33

    
34
/* include all configuration functions */
35
require_once("config.inc");
36
require_once("functions.inc");
37

    
38
/* Optimize Unbound for environment */
39
function unbound_optimization() {
40
	global $config;
41

    
42
	$optimization_settings = array();
43

    
44
	/* 
45
	 * Set the number of threads equal to number of CPUs.
46
	 * Use 1 to disable threading, if for some reason this sysctl fails.
47
	 */
48
	$numprocs = intval(get_single_sysctl('kern.smp.cpus'));
49
	if ($numprocs > 0)
50
		$optimization['number_threads'] = "num-threads: {$numprocs}";
51
	else
52
		$optimization['number_threads'] = "num-threads: 1";
53

    
54
	// Slabs to help reduce lock contention.
55
	if ($numprocs > 4) {
56
		$optimization['msg_cache_slabs'] = "msg-cache-slabs: {$numprocs}";
57
		$optimization['rrset_cache_slabs'] = "rrset-cache-slabs: {$numprocs}";
58
		$optimization['infra_cache_slabs'] = "infra-cache-slabs: {$numprocs}";
59
		$optimization['key_cache_slabs'] = "key-cache-slabs: {$numprocs}";
60
	} else {
61
		$optimization['msg_cache_slabs'] = "msg-cache-slabs: 4";
62
		$optimization['rrset_cache_slabs'] = "rrset-cache-slabs: 4";
63
		$optimization['infra_cache_slabs'] = "infra-cache-slabs: 4";
64
		$optimization['key_cache_slabs'] = "key-cache-slabs: 4";
65
	}
66

    
67
	// Memory usage default of 4MB
68
	$optimization['msg_cache_size'] = "msg-cache-size: 4m";
69
	$optimization['rrset_cache_size'] = "rrset-cache-size: 8m";
70

    
71
	// More outgoing connections per thread otherwise assign a default of 4096 for a single thread
72
	if ($numprocs > 0) {
73
		$or = (1024/$numprocs) - 50;
74
		$optimization['outgoing_range'] = "outgoing-range: {$or}";
75
	} else
76
		$optimization['outgoing_range'] = "outgoing-range: {4096}";
77

    
78
	/*
79
	 * Larger socket buffer for busy servers
80
	 * Check that it is set to 4MB (by default the OS has it configured to 4MB)
81
	 */
82
	if (is_array($config['sysctl']) && is_array($config['sysctl']['item'])) {
83
		foreach ($config['sysctl']['item'] as $tunable) {
84
			if ($tunable['tunable'] == 'kern.ipc.maxsockbuf') {
85
				$so = floor(($tunable['value']/1024/1024)-1);
86
				// Check to ensure that the number is not a negative
87
				if ($so > 0)
88
					$optimization['so_rcvbuf'] = "so-rcvbuf: {$so}m";
89
				else
90
					unset($optimization['so_rcvbuf']);
91
			}
92
		}
93
	}
94
	// Safety check in case kern.ipc.maxsockbuf is not available.
95
	if (!isset($optimization['so_rcvbuf']))
96
		$optimization['so_rcvbuf'] = "#so-rcvbuf: 4m";
97

    
98
	return $optimization;
99

    
100
}
101

    
102
function unbound_generate_config() {
103
	global $config, $g;
104

    
105
	// Setup optimization
106
	$optimization = unbound_optimization();
107

    
108
	// Setup DNSSEC support
109
	if (isset($config['unbound']['dnssec'])) {
110
		$module_config = "validator iterator";
111
		$anchor_file = "auto-trust-anchor-file: {$g['unbound_chroot_path']}/root.key";
112
	} else
113
		$module_config = "iterator";
114

    
115
	// Setup DNS Rebinding
116
	if (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
117
		// Private-addresses for DNS Rebinding
118
		$private_addr = <<<EOF
119
# For DNS Rebinding prevention
120
private-address: 10.0.0.0/8
121
private-address: 172.16.0.0/12
122
private-address: 192.168.0.0/16
123
private-address: 192.254.0.0/16
124
private-address: fd00::/8
125
private-address: fe80::/10
126
EOF;
127
	}
128

    
129
	// Determine interfaces to run on
130
	$bindints = "";
131
	if (!empty($config['unbound']['active_interface'])) {
132
		$active_interfaces = explode(",", $config['unbound']['active_interface']);
133
		foreach($active_interfaces as $ubif) {
134
			$intip = get_interface_ip($ubif);
135
			if (!is_null($intip))
136
				$bindints .= "interface: $intip\n";
137
			$intip = get_interface_ipv6($ubif);
138
			if (!is_null($intip))
139
				$bindints .= "interface: $intip\n";
140
		}
141
	} else {
142
		$bindints .= "interface: 0.0.0.0\n";
143
		$bindints .= "interface: ::0\n";
144
	}
145

    
146
	// Determine interfaces to run on
147
	$outgoingints = "";
148
	if (!empty($config['unbound']['outgoing_interface'])) {
149
		$outgoingints = "# Outgoing interfaces to be used\n";
150
		$outgoing_interfaces = explode(",", $config['unbound']['outgoing_interface']);
151
		foreach($outgoing_interfaces as $outif) {
152
			$outip = get_interface_ip($outif);
153
			if (!is_null($outip))
154
				$outgoingints .= "outgoing-interface: $outip\n";
155
			$outip = get_interface_ipv6($outif);
156
			if (!is_null($outip))
157
				$outgoingints .= "outgoing-interface: $outip\n";
158
		}
159
	}
160

    
161
	// Allow DNS Rebind for forwarded domains
162
	if ((isset($config['unbound']['domainoverrides']) && is_array($config['unbound']['domainoverrides'])) && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
163
		$private_domains = "# Set private domains in case authoritative name server returns a Private IP address\n";
164
		$private_domains .= unbound_add_domain_overrides(true);
165
	}
166

    
167
	// Configure static Host entries
168
	unbound_add_host_entries();
169

    
170
	// Configure Domain Overrides
171
	unbound_add_domain_overrides();
172

    
173
	// Configure Unbound statistics
174
	$statistics = unbound_statistics();
175

    
176
	// Configure Unbound access-lists
177
	unbound_acls_config();
178

    
179
	// Add custom Unbound options
180
	if ($config['unbound']['custom_options']) {
181
		$custom_option = "# Unbound custom option";
182
		foreach (preg_split('/\s+/', $config['unbound']['custom_options']) as $ent)
183
			$custom_option .= $ent."\n";
184
	}
185

    
186
	// Server configuration variables
187
	$port = (is_port($config['unbound']['port'])) ? $config['unbound']['port'] : "53";
188
	$hide_id = ($config['unbound']['hide_id'] == "on") ? "yes" : "no";
189
	$hide_version = ($config['unbound']['hide_version'] == "on") ? "yes" : "no";
190
	$harden_glue = ($config['unbound']['harden_glue'] == "on") ? "yes" : "no";
191
	$harden_dnssec_stripped = ($config['unbound']['harden_dnssec_stripped'] == "on") ? "yes" : "no";
192
	$prefetch = ($config['unbound']['prefetch'] == "on") ? "yes" : "no";
193
	$prefetch_key = ($config['unbound']['prefetch_key'] == "on") ? "yes" : "no";
194
	$outgoing_num_tcp = (!empty($config['unbound']['outgoing_num_tcp'])) ? $config['unbound']['outgoing_num_tcp'] : "10";
195
	$incoming_num_tcp = (!empty($config['unbound']['incoming_num_tcp'])) ? $config['unbound']['incoming_num_tcp'] : "10";
196
	$edns_buffer_size = (!empty($config['unbound']['edns_buffer_size'])) ? $config['unbound']['edns_buffer_size'] : "4096";
197
	$num_queries_per_thread = (!empty($config['unbound']['num_queries_per_thread'])) ? $config['unbound']['num_queries_per_thread'] : "4096";
198
	$jostle_timeout = (!empty($config['unbound']['jostle_timeout'])) ? $config['unbound']['jostle_timeout'] : "200";
199
	$cache_max_ttl = (!empty($config['unbound']['cache_max_ttl'])) ? $config['unbound']['cache_max_ttl'] : "86400";
200
	$cache_min_ttl = (!empty($config['unbound']['cache_min_ttl'])) ? $config['unbound']['cache_min_ttl'] : "0";
201
	$infra_host_ttl = (!empty($config['unbound']['infra_host_ttl'])) ? $config['unbound']['infra_host_ttl'] : "900";
202
	$infra_lame_ttl = (!empty($config['unbound']['infra_lame_ttl'])) ? $config['unbound']['infra_lame_ttl'] : "900";
203
	$infra_cache_numhosts = (!empty($config['unbound']['infra_cache_numhosts'])) ? $config['unbound']['infra_cache_numhosts'] : "10000";
204
	$unwanted_reply_threshold = (!empty($config['unbound']['unwanted_reply_threshold'])) ? $config['unbound']['unwanted_reply_threshold'] : "0";
205
	$verbosity = isset($config['unbound']['loglevel']) ? $config['unbound']['loglevel'] : 1;
206

    
207
	// Set up forwarding if it configured
208
	if (isset($config['unbound']['forwarding'])) {
209
		$dnsservers = array();
210
		if (isset($config['system']['dnsallowoverride'])) {
211
			$ns = array_unique(get_nameservers());
212
			foreach($ns as $nameserver) {
213
				if ($nameserver)
214
					$dnsservers[] = $nameserver;
215
			}
216
		} else {
217
			$ns = array_unique(get_dns_servers());
218
			foreach($ns as $nameserver) {
219
				if ($nameserver)
220
					$dnsservers[] = $nameserver;
221
			}
222
		}
223

    
224
		if (!empty($dnsservers)) {
225
			$forward_conf .=<<<EOD
226
# Forwarding
227
forward-zone:
228
	name: "."
229

    
230
EOD;
231
			foreach($dnsservers as $dnsserver)
232
				$forward_conf .= "\tforward-addr: $dnsserver\n";
233
		}
234
	} else
235
		$forward_conf = "";
236

    
237
	$unboundconf = <<<EOD
238
##########################
239
# Unbound Configuration
240
##########################
241

    
242
##
243
# Server configuration
244
##
245
server:
246
chroot: {$g['unbound_chroot_path']}
247
username: "unbound"
248
directory: "{$g['unbound_chroot_path']}"
249
pidfile: "/var/run/unbound.pid"
250
use-syslog: yes
251
port: {$port}
252
verbosity: {$verbosity}
253
harden-referral-path: no
254
do-ip4: yes
255
do-ip6: yes
256
do-udp: yes
257
do-tcp: yes
258
do-daemonize: yes
259
module-config: "{$module_config}"
260
unwanted-reply-threshold: 0
261
num-queries-per-thread: 1024
262
jostle-timeout: 200
263
infra-host-ttl: 900
264
infra-lame-ttl: 900
265
infra-cache-numhosts: 10000
266
outgoing-num-tcp: 10
267
incoming-num-tcp: 10
268
edns-buffer-size: 4096
269
cache-max-ttl: {$cache_max_ttl}
270
cache-min-ttl: {$cache_min_ttl}
271
harden-dnssec-stripped: yes
272
{$optimization['number_threads']}
273
{$optimization['msg_cache_slabs']}
274
{$optimization['rrset_cache_slabs']}
275
{$optimization['infra_cache_slabs']}
276
{$optimization['key_cache_slabs']}
277
{$optimization['msg_cache_size']}
278
{$optimization['rrset_cache_size']}
279
{$optimization['outgoing_range']}
280
{$optimization['so_rcvbuf']}
281
{$anchor_file}
282
prefetch: {$prefetch}
283
prefetch-key: {$prefetch_key}
284
# Statistics
285
{$statistics}
286
# Interface IP(s) to bind to
287
{$bindints}
288
{$outgoingints}
289

    
290
# DNS Rebinding
291
{$private_addr}
292
{$private_domains}
293

    
294
# Access lists
295
include: {$g['unbound_chroot_path']}/access_lists.conf
296

    
297
# Static host entries
298
include: {$g['unbound_chroot_path']}/host_entries.conf
299

    
300
# Domain overrides
301
include: {$g['unbound_chroot_path']}/domainoverrides.conf
302
{$forward_conf}
303

    
304
{$custom_options}
305

    
306
###
307
# Remote Control Config
308
###
309
include: {$g['unbound_chroot_path']}/remotecontrol.conf
310

    
311
EOD;
312

    
313
	file_put_contents("{$g['unbound_chroot_path']}/unbound.conf", $unboundconf);
314

    
315
	return 0;
316
}
317

    
318
function unbound_remote_control_setup() {
319
	global $g;
320

    
321
	if (!file_exists("{$g['unbound_chroot_path']}/remotecontrol.conf") || !file_exists("{$g['unbound_chroot_path']}/unbound_control.key")) {
322
		$remotcfg = <<<EOF
323
remote-control:
324
	control-enable: yes
325
	control-interface: 127.0.0.1
326
	control-port: 953
327
	server-key-file: "{$g['unbound_chroot_path']}/unbound_server.key"
328
	server-cert-file: "{$g['unbound_chroot_path']}/unbound_server.pem"
329
	control-key-file: "{$g['unbound_chroot_path']}/unbound_control.key"
330
	control-cert-file: "{$g['unbound_chroot_path']}/unbound_control.pem"
331

    
332
EOF;
333

    
334
		file_put_contents("{$g['unbound_chroot_path']}/remotecontrol.conf", $remotcfg);
335

    
336
		// Generate our keys
337
		do_as_unbound_user("unbound-control-setup");
338

    
339
	}
340
}
341

    
342

    
343
// Read /etc/hosts
344
function read_hosts() {
345

    
346
	/* Open /etc/hosts and extract the only dhcpleases info
347
	 * XXX - to convert to an unbound C library which reads /etc/hosts automatically
348
	 */
349
	$etc_hosts = array();
350
	foreach (file('/etc/hosts') as $line) {
351
		$d = preg_split('/\s/', $line, -1, PREG_SPLIT_NO_EMPTY);
352
		if (empty($d) || substr(reset($d), 0, 1) == "#")
353
			continue;
354
		if ($d[3] == "#") {
355
			$ip = array_shift($d);
356
			$fqdn = array_shift($d);
357
			$name = array_shift($d);
358
			if ($fqdn != "empty") {
359
				if ($name != "empty")
360
					array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn", name => "$name"));
361
				else
362
					array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn"));
363
			}
364
		}
365
	}
366
	return $etc_hosts;
367
}
368

    
369
function sync_unbound_service() {
370
	global $config, $g;
371

    
372
	// Configure chroot
373
	if (!is_dir($g['unbound_chroot_path'])) {
374
		mkdir($g['unbound_chroot_path']);
375
		chown($g['unbound_chroot_path'], "unbound");
376
		chgrp($g['unbound_chroot_path'], "unbound");
377
	}
378

    
379
	// Configure our Unbound service
380
	do_as_unbound_user("unbound-anchor");
381
	unbound_remote_control_setup();
382
	unbound_generate_config();
383
	do_as_unbound_user("start");
384
	require_once("service-utils.inc");
385
	if (is_service_running("unbound"))
386
		do_as_unbound_user("restore_cache");
387

    
388
}
389

    
390
function unbound_acl_id_used($id) {
391
	global $config;
392

    
393
	if (is_array($config['unbound']['acls']))
394
		foreach($config['unbound']['acls'] as & $acls)
395
			if ($id == $acls['aclid'])
396
				return true;
397

    
398
	return false;
399
}
400

    
401
function unbound_get_next_id() {
402
	$aclid = 0;
403
	while(unbound_acl_id_used($aclid))
404
		$aclid++;
405
	return $aclid;
406
}
407

    
408
// Execute commands as the user unbound
409
function do_as_unbound_user($cmd) {
410
	global $g;
411

    
412
	switch ($cmd) {
413
	case "start":
414
		mwexec("/usr/sbin/unbound -c {$g['unbound_chroot_path']}/unbound.conf");
415
		break;
416
	case "stop":
417
		mwexec("echo '/usr/sbin/unbound-control stop' | /usr/bin/su -m unbound", true);
418
		break;
419
	case "unbound-anchor":
420
		mwexec("echo '/usr/sbin/unbound-anchor -a {$g['unbound_chroot_path']}/root.key' | /usr/bin/su -m unbound", true);
421
		break;
422
	case "unbound-control-setup":
423
		mwexec("echo '/usr/sbin/unbound-control-setup -d {$g['unbound_chroot_path']}' | /usr/bin/su -m unbound", true);
424
		break;
425
	default:
426
		break;
427
	}
428
}
429

    
430
function unbound_add_domain_overrides($pvt=false) {
431
	global $config, $g;
432

    
433
	$domains = $config['unbound']['domainoverrides'];
434

    
435
	$sorted_domains = msort($domains, "domain");
436
	$result = array();
437
	foreach($sorted_domains as $domain) {
438
		$domain_key = current($domain);
439
		if (!isset($result[$domain_key]))
440
			$result[$domain_key] = array();
441
		$result[$domain_key][] = $domain['ip'];
442
	}
443

    
444
	// Domain overrides that have multiple entries need multiple stub-addr: added
445
	$domain_entries = "";
446
	foreach($result as $domain=>$ips) {
447
		if ($pvt == true) {
448
			$domain_entries .= "private-domain: \"$domain\"\n";
449
			$domain_entries .= "domain-insecure: \"$domain\"\n";
450
		} else {
451
			$domain_entries .= "stub-zone:\n";
452
			$domain_entries .= "\tname: \"$domain\"\n";
453
			foreach($ips as $ip)
454
				$domain_entries .= "\tstub-addr: $ip\n";
455
			$domain_entries .= "\tstub-prime: no\n";
456
		}
457
	}
458

    
459
	if ($pvt == true)
460
		return $domain_entries;
461
	else
462
		file_put_contents("{$g['unbound_chroot_path']}/domainoverrides.conf", $domain_entries);
463
}
464

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

    
468
	$unbound_entries = "local-zone: \"{$config['system']['domain']}\" transparent\n";
469
	// IPv4 entries
470
	$unbound_entries .= "local-data-ptr: \"127.0.0.1 localhost\"\n";
471
	$unbound_entries .= "local-data: \"localhost A 127.0.0.1\"\n";
472
	$unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} A 127.0.0.1\"\n";
473
	// IPv6 entries
474
	$unbound_entries .= "local-data-ptr: \"::1 localhost\"\n";
475
	$unbound_entries .= "local-data: \"localhost AAAA ::1\"\n";
476
	$unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} AAAA ::1\"\n";
477

    
478
	$listen_addresses = "";
479
	if (isset($config['unbound']['interface'])) {
480
		$interfaces = explode(",", $config['unbound']['interface']);
481
		foreach ($interfaces as $interface) {
482
			if (is_ipaddrv4($interface)) {
483
				$unbound_entries .= "local-data-ptr: \"{$interface} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
484
				$unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$interface}\"\n";
485
				$unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$interface}\"\n";
486
			} else if (is_ipaddrv6($interface)) {
487
				$unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$interface}\"\n";
488
				$unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$interface}\"\n";
489
			} else {
490
				$if = get_real_interface($interface);
491
				if (does_interface_exist($if)) {
492
					$laddr = find_interface_ip($if);
493
					if (is_ipaddrv4($laddr)) {
494
						$unbound_entries .= "local-data-ptr: \"{$laddr} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
495
						$unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$laddr}\"\n";
496
						$unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$laddr}\"\n";
497
					}
498
					$laddr6 = find_interface_ipv6($if);
499
					if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
500
						$unbound_entries .= "local-data-ptr: \"{$laddr6} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
501
						$unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$laddr}\"\n";
502
						$unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$laddr}\"\n";
503
					}
504
				}
505
			}
506
		}
507
	}
508

    
509
	// Static Host entries
510
	if (isset($config['unbound']['hosts'])) {
511
		$host_entries = "";
512
		$added_item = array();
513
		foreach($config['unbound']['hosts'] as $host) {
514
			$current_host = $host['host'];
515
			if ($host['host'] != "")
516
				$host['host'] = $host['host'].".";
517
			if (!$added_item[$current_host]) {
518
				$host_entries .= "local-data-ptr: \"{$host['ip']} {$host['host']}{$host['domain']}\"\n";
519
				if (is_ipaddrv6($host['ip']))
520
					$host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN AAAA {$host['ip']}\"\n";
521
				else
522
					$host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN A {$host['ip']}\"\n";
523
				if (!empty($host['descr']) && isset($config['unbound']['txtsupport']))
524
					$host_entries .= "local-data: '{$host['host']}{$host['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
525

    
526
				// Do not add duplicate entries
527
				$added_item[$current_host] = true;
528
			}
529
		}
530
		$unbound_entries .= $host_entries;
531
	}
532

    
533
	// Static DHCP entries
534
	$host_entries = "";
535
	if (isset($config['unbound']['regdhcpstatic']) && is_array($config['dhcpd'])) {
536
		foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf)
537
			if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable']))
538
				foreach ($dhcpifconf['staticmap'] as $host)
539
					if ($host['ipaddr'] && $host['hostname']) {
540
						$host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['hostname']}.{$config['system']['domain']}\"\n";
541
						$host_entries .= "local-data: \"{$host['hostname']}.{$config['system']['domain']} IN A {$host['ipaddr']}\"\n";
542
						if (!empty($host['descr']) && $unboundcfg['txtsupport'] == 'on')
543
							$host_entries .= "local-data: '{$host['hostname']}.{$config['system']['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
544
					}
545
		$unbound_entries .= $host_entries;
546
	}
547

    
548
	// Handle DHCPLeases added host entries
549
	$dhcplcfg = read_hosts();
550
	$host_entries = "";
551
	if (is_array($dhcplcfg)) {
552
		foreach($dhcplcfg as $key=>$host) {
553
			$host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['fqdn']}\"\n";
554
			$host_entries .= "local-data: \"{$host['fqdn']} IN A {$host['ipaddr']}\"\n";
555
			if (!empty($host['name'])) {
556
				$host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['name']}\"\n";
557
				$host_entries .= "local-data: \"{$host['name']} IN A {$host['ipaddr']}\"\n";
558
			}
559
		}
560
		$unbound_entries .= $host_entries;
561
	}
562

    
563
	// Write out entries
564
	file_put_contents("{$g['unbound_chroot_path']}/host_entries.conf", $unbound_entries);
565
}
566

    
567
function unbound_control($action) {
568
	global $config, $g;
569

    
570
	$cache_dumpfile = "/var/tmp/unbound_cache";
571

    
572
	switch ($action) {
573
	case "start":
574
		// Start Unbound
575
		if ($config['unbound']['enable'] == "on") {
576
			if (!is_service_running("unbound"))
577
				do_as_unbound_user("start");
578
		}
579
		break;
580
	case "stop":
581
		if ($config['unbound']['enable'] == "on")
582
			do_as_unbound_user("stop");
583
		break;
584
	case "reload":
585
		if ($config['unbound']['enable'] == "on")
586
			do_as_unbound_user("reload");
587
		break;
588
	case "dump_cache":
589
		// Dump Unbound's Cache
590
		if ($config['unbound']['dumpcache'] == "on")
591
			do_as_unbound_user("dump_cache");
592
		break;
593
	case "restore_cache":
594
		// Restore Unbound's Cache
595
		if ((is_service_running("unbound")) && ($config['unbound']['dumpcache'] == "on")) {
596
			if (file_exists($cache_dumpfile) && filesize($cache_dumpfile) > 0)
597
				do_as_unbound_user("load_cache < /var/tmp/unbound_cache");
598
		}
599
		break;
600
	default:
601
		break;
602

    
603
	}
604
}
605

    
606
// Generation of Unbound statistics
607
function unbound_statistics() {
608
	global $config;
609

    
610
	if ($config['stats'] == "on") {
611
		$stats_interval = $config['unbound']['stats_interval'];
612
		$cumulative_stats = $config['cumulative_stats'];
613
		if ($config['extended_stats'] == "on")
614
			$extended_stats = "yes";
615
		else
616
			$extended_stats = "no";
617
	} else {
618
		$stats_interval = "0";
619
		$cumulative_stats = "no";
620
		$extended_stats = "no";
621
	}
622
	/* XXX To do - add RRD graphs */
623
	$stats = <<<EOF
624
# Unbound Statistics
625
statistics-interval: {$stats_interval}
626
extended-statistics: yes
627
statistics-cumulative: yes
628

    
629
EOF;
630

    
631
	return $stats;
632
}
633

    
634
// Unbound Access lists
635
function unbound_acls_config() {
636
	global $g, $config;
637

    
638
	$aclcfg = "access-control: 127.0.0.1/32 allow\n";
639
	$aclcfg .= "access-control: ::1 allow\n";
640
	// Add our networks for active interfaces including localhost
641
	if (!empty($config['unbound']['active_interface']))
642
		$active_interfaces = array_flip(explode(",", $config['unbound']['active_interface']));
643
	else
644
		$active_interfaces = get_configured_interface_with_descr();
645

    
646
	$bindints = "";
647
	foreach($active_interfaces as $ubif => $ifdesc) {
648
		$ifip = get_interface_ip($ubif);
649
		if (!is_null($ifip)) {
650
			$subnet_bits = get_interface_subnet($ubif);
651
			$subnet_ip = gen_subnet($ifip, $subnet_bits);
652
			$aclcfg .= "access-control: {$subnet_ip}/{$subnet_bits} allow\n";
653
		}
654
		$ifip = get_interface_ipv6($ubif);
655
		if (!is_null($ifip)) {
656
			$subnet_bits = get_interface_subnetv6($ubif);
657
			$subnet_ip = gen_subnetv6($ifip, $subnet_bits);
658
			$aclcfg .= "access-control: {$subnet_ip}/{$subnet_bits} allow\n";
659
		}
660
	}
661

    
662
	// Configure the custom ACLs
663
	if (is_array($config['unbound']['acls'])) {
664
		foreach($config['unbound']['acls'] as $unbound_acl) {
665
			$aclcfg .= "#{$unbound_acl['aclname']}\n";
666
			foreach($unbound_acl['row'] as $network) {
667
				if ($unbound_acl['aclaction'] == "allow snoop")
668
					$unbound_acl['aclaction'] = "allow_snoop";
669
				$aclcfg .= "access-control: {$network['acl_network']}/{$network['mask']} {$unbound_acl['aclaction']}\n";
670
			}
671
		}
672
	}
673
	// Write out Access list
674
	file_put_contents("{$g['unbound_chroot_path']}/access_lists.conf", $aclcfg);
675

    
676
}
677

    
678
// Generate hosts and reload services
679
function unbound_hosts_generate() {
680
	// Generate our hosts file
681
	unbound_add_host_entries();
682

    
683
	// Reload our service to read the updates
684
	unbound_control("reload");
685
}
686

    
687
?>
(54-54/68)