Project

General

Profile

Download (22.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
    unbound.inc
4
    part of the pfSense project (https://www.pfsense.org)
5

    
6
    originally part of m0n0wall (http://m0n0.ch/wall)
7
    Copyright (C) 2014 Warren Baker <warren@decoy.co.za>
8
    All rights reserved.
9

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

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

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

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

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

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

    
44
    $optimization_settings = array();
45
    
46
    /* 
47
     * Set the number of threads equal to number of CPUs.
48
     * Use 1 to disable threading, if for some reason this sysctl fails.
49
     */
50
    $numprocs = intval(trim(`/sbin/sysctl kern.smp.cpus | /usr/bin/cut -d" " -f2`));
51
    if ($numprocs > 0)
52
        $optimization['number_threads'] = "num-threads: {$numprocs}";
53
    else
54
        $optimization['number_threads'] = "num-threads: 1";
55
    
56
    // Slabs to help reduce lock contention.
57
    if ($numprocs > 4) {
58
        $optimization['msg_cache_slabs'] = "msg-cache-slabs: {$numprocs}";
59
        $optimization['rrset_cache_slabs'] = "rrset-cache-slabs: {$numprocs}";
60
        $optimization['infra_cache_slabs'] = "infra-cache-slabs: {$numprocs}";
61
        $optimization['key_cache_slabs'] = "key-cache-slabs: {$numprocs}";
62
    } else {
63
        $optimization['msg_cache_slabs'] = "msg-cache-slabs: 4";
64
        $optimization['rrset_cache_slabs'] = "rrset-cache-slabs: 4";
65
        $optimization['infra_cache_slabs'] = "infra-cache-slabs: 4";
66
        $optimization['key_cache_slabs'] = "key-cache-slabs: 4";
67
    }
68
    
69
    // Memory usage default of 4MB
70
    $optimization['msg_cache_size'] = "msg-cache-size: 4m";
71
    $optimization['rrset_cache_size'] = "rrset-cache-size: 8m";
72

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

    
80
    /*
81
     * Larger socket buffer for busy servers
82
     * Check that it is set to 4MB (by default the OS has it configured to 4MB)
83
     */
84
    foreach ($config['sysctl']['item'] as $tunable) {
85
        if ($tunable['tunable'] == 'kern.ipc.maxsockbuf') {
86
            $so = floor(($tunable['value']/1024/1024)-1);
87
            // Check to ensure that the number is not a negative
88
            if ($so > 0)
89
                $optimization['so_rcvbuf'] = "so-rcvbuf: {$so}m";
90
            else
91
                unset($optimization['so_rcvbuf']);
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_status'])) {
110
        $module_config = "validator iterator";
111
        $anchor_file = "auto-trust-anchor-file: {$g['unbound_chroot_path']}/root-trust-anchor";
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
    // Allow DNS Rebind for forwarded domains
130
    if ((isset($config['unbound']['domainoverrides']) && is_array($config['unbound']['domainoverrides'])) && !isset($config['system']['webgui']['nodnsrebindcheck'])) {
131
        $private_domains = "# Set private domains in case authoritative name server returns a Private IP address";
132
        $private_domains .= unbound_add_domain_overrides(true);
133
    }
134

    
135
    // Configure static Host entries
136
    unbound_add_host_entries();
137

    
138
    // Configure Domain Overrides
139
    unbound_add_domain_overrides();
140

    
141
    // Configure Unbound statistics
142
    $statistics = unbound_statistics();
143

    
144
    // Configure Unbound access-lists
145
    unbound_acls_config();
146

    
147
    // Add custom Unbound options
148
    if ($config['unbound']['custom_options']) {
149
        $custom_option = "# Unbound custom option";
150
        foreach (preg_split('/\s+/', $config['unbound']['custom_options']) as $ent)
151
            $custom_option .= $ent."\n";
152
    }
153

    
154
    // Server configuration variables
155
    $port = (is_port($config['unbound']['port'])) ? $config['unbound']['port'] : "53";
156
    $hide_id = ($config['unbound']['hide_id'] == "on") ? "yes" : "no";
157
    $hide_version = ($config['unbound']['hide_version'] == "on") ? "yes" : "no";
158
    $harden_glue = ($config['unbound']['harden_glue'] == "on") ? "yes" : "no";
159
    $harden_dnssec_stripped = ($config['unbound']['harden_dnssec_stripped'] == "on") ? "yes" : "no";
160
    $prefetch = ($config['unbound']['prefetch'] == "on") ? "yes" : "no";
161
    $prefetch_key = ($config['unbound']['prefetch_key'] == "on") ? "yes" : "no";
162
    $outgoing_num_tcp = (!empty($config['unbound']['outgoing_num_tcp'])) ? $config['unbound']['outgoing_num_tcp'] : "10";
163
    $incoming_num_tcp = (!empty($config['unbound']['incoming_num_tcp'])) ? $config['unbound']['incoming_num_tcp'] : "10";
164
    $edns_buffer_size = (!empty($config['unbound']['edns_buffer_size'])) ? $config['unbound']['edns_buffer_size'] : "4096";
165
    $num_queries_per_thread = (!empty($config['unbound']['num_queries_per_thread'])) ? $config['unbound']['num_queries_per_thread'] : "4096";
166
    $jostle_timeout = (!empty($config['unbound']['jostle_timeout'])) ? $config['unbound']['jostle_timeout'] : "200";
167
    $cache_max_ttl = (!empty($config['unbound']['cache_max_ttl'])) ? $config['unbound']['cache_max_ttl'] : "86400";
168
    $cache_min_ttl = (!empty($config['unbound']['cache_min_ttl'])) ? $config['unbound']['cache_min_ttl'] : "0";
169
    $infra_host_ttl = (!empty($config['unbound']['infra_host_ttl'])) ? $config['unbound']['infra_host_ttl'] : "900";
170
    $infra_lame_ttl = (!empty($config['unbound']['infra_lame_ttl'])) ? $config['unbound']['infra_lame_ttl'] : "900";
171
    $infra_cache_numhosts = (!empty($config['unbound']['infra_cache_numhosts'])) ? $config['unbound']['infra_cache_numhosts'] : "10000";
172
    $unwanted_reply_threshold = (!empty($config['unbound']['unwanted_reply_threshold'])) ? $config['unbound']['unwanted_reply_threshold'] : "0";
173
    $verbosity = isset($config['unbound']['loglevel']) ? $config['unbound']['loglevel'] : 1;
174

    
175
    // Set up forwarding if it configured
176
    if (isset($config['unbound']['forwarding'])) {
177
        $dnsservers = array();
178
        if (isset($config['system']['dnsallowoverride'])) {
179
            $ns = array_unique(get_nameservers());
180
            foreach($ns as $nameserver) {
181
                if ($nameserver)
182
                    $dnsservers[] = $nameserver;
183
            }
184
        } else {
185
            $ns = array_unique(get_dns_servers());
186
            foreach($ns as $nameserver) {
187
                if ($nameserver)
188
                    $dnsservers[] = $nameserver;
189
            }
190
        }
191

    
192
        if (!empty($dnsservers)) {
193
            $forward_conf .=<<<EOD
194
# Forwarding
195
forward-zone:
196
    name: "."
197

    
198
EOD;
199
            foreach($dnsservers as $dnsserver)
200
                $forward_conf .= "\tforward-addr: $dnsserver\n";
201
        }
202
    } else
203
        $forward_conf = "";
204

    
205
    $unboundconf = <<<EOD
206
##########################
207
# Unbound Configuration
208
##########################
209

    
210
##
211
# Server configuration
212
##
213
server:
214
chroot: {$g['unbound_chroot_path']}
215
username: "unbound"
216
directory: "{$g['unbound_chroot_path']}"
217
pidfile: "/var/run/unbound.pid"
218
use-syslog: yes
219
port: {$port}
220
verbosity: {$verbosity}
221
harden-referral-path: no
222
do-ip4: yes
223
do-ip6: yes
224
do-udp: yes
225
do-tcp: yes
226
do-daemonize: yes
227
module-config: "{$module_config}"
228
unwanted-reply-threshold: 0
229
num-queries-per-thread: 1024
230
jostle-timeout: 200
231
infra-host-ttl: 900
232
infra-lame-ttl: 900
233
infra-cache-numhosts: 10000
234
outgoing-num-tcp: 10
235
incoming-num-tcp: 10
236
edns-buffer-size: 4096
237
cache-max-ttl: {$cache_max_ttl}
238
cache-min-ttl: {$cache_min_ttl}
239
harden-dnssec-stripped: yes
240
{$optimization['number_threads']}
241
{$optimization['msg_cache_slabs']}
242
{$optimization['rrset_cache_slabs']}
243
{$optimization['infra_cache_slabs']}
244
{$optimization['key_cache_slabs']}
245
{$optimization['msg_cache_size']}
246
{$optimization['rrset_cache_size']}
247
{$optimization['outgoing_range']}
248
{$optimization['so_rcvbuf']}
249
{$anchor_file}
250
prefetch: {$prefetch}
251
prefetch-key: {$prefetch_key}
252
# Statistics
253
{$statistics}
254
# Interface IP(s) to bind to
255
interface: 0.0.0.0
256
interface: ::0
257

    
258
# DNS Rebinding
259
{$private_addr}
260
{$private_domains}
261

    
262
# Static host entries
263
include: {$g['unbound_chroot_path']}/host_entries.conf
264

    
265
# Domain overrides
266
include: {$g['unbound_chroot_path']}/domainove
267
{$forward_conf}
268

    
269
{$custom_options}
270

    
271
###
272
# Remote Control Config
273
###
274
include: {$g['unbound_chroot_path']}/remotecontrol.conf
275

    
276
EOD;
277

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

    
280
    return 0;
281
}
282

    
283
function unbound_remote_control_setup() {
284
    global $g;
285

    
286
    if (!file_exists("{$g['unbound_chroot_path']}/remotecontrol.conf") || !file_exists("{$g['unbound_chroot_path']}/unbound_control.key")) {
287
        $remotcfg = <<<EOF
288
remote-control:
289
    control-enable: yes
290
    control-interface: 127.0.0.1
291
    control-port: 953
292
    server-key-file: "{$g['unbound_chroot_path']}/unbound_server.key"
293
    server-cert-file: "{$g['unbound_chroot_path']}/unbound_server.pem"
294
    control-key-file: "{$g['unbound_chroot_path']}/unbound_control.key"
295
    control-cert-file: "{$g['unbound_chroot_path']}/unbound_control.pem"
296

    
297
EOF;
298

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

    
301
        // Generate our keys
302
        do_as_unbound_user("unbound-control-setup");
303

    
304
    }
305
}
306

    
307

    
308
// Read /etc/hosts
309
function read_hosts() {
310

    
311
    /* Open /etc/hosts and extract the only dhcpleases info
312
     * XXX - to convert to an unbound C library which reads /etc/hosts automatically
313
     */
314
    $etc_hosts = array();
315
    foreach (file('/etc/hosts') as $line) {
316
        $d = preg_split('/\s/', $line, -1, PREG_SPLIT_NO_EMPTY);
317
        if (empty($d) || substr(reset($d), 0, 1) == "#")
318
            continue;
319
        if ($d[3] == "#") {
320
            $ip = array_shift($d);
321
            $fqdn = array_shift($d);
322
            $name = array_shift($d);
323
            if ($fqdn != "empty") {
324
                if ($name != "empty")
325
                    array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn", name => "$name"));
326
                else
327
                    array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn"));
328
            }
329
        }
330
    }
331
    return $etc_hosts;
332
}
333

    
334
function sync_unbound_service() {
335
    global $config, $g;
336

    
337
    // Configure chroot
338
    if (!is_dir($g['unbound_chroot_path'])) {
339
        mkdir($g['unbound_chroot_path']);
340
        chown($g['unbound_chroot_path'], "unbound");
341
        chgrp($g['unbound_chroot_path'], "unbound");
342
    }
343

    
344
    // Configure our Unbound service
345
    do_as_unbound_user("unbound-anchor");
346
    unbound_remote_control_setup();
347
    unbound_generate_config();
348
    do_as_unbound_user("start");
349
    require_once("service-utils.inc");
350
    if (is_service_running("unbound"))
351
        do_as_unbound_user("restore_cache");
352

    
353
}
354

    
355
function unbound_acl_id_used($id) {
356
    global $config;
357

    
358
    if (is_array($config['unbound']['acls']))
359
        foreach($config['unbound']['acls'] as & $acls)
360
            if ($id == $acls['aclid'])
361
                return true;
362

    
363
    return false;
364
}
365

    
366
function unbound_get_next_id() {
367
    $aclid = 0;
368
    while(unbound_acl_id_used($aclid))
369
        $aclid++;
370
    return $aclid;
371
}
372

    
373
// Execute commands as the user unbound
374
function do_as_unbound_user($cmd) {
375
    global $g;
376

    
377
    switch ($cmd) {
378
        case "start":
379
            mwexec("/usr/sbin/unbound -c{$g['unbound_chroot_path']}/unbound.conf");
380
            break;
381
        case "stop":
382
            mwexec("echo '/usr/sbin/unbound-control stop' | /usr/bin/su -m unbound", true);
383
            break;
384
        case "unbound-anchor":
385
            mwexec("echo '/usr/sbin/unbound-anchor -a {$g['unbound_chroot_path']}/root.key' | /usr/bin/su -m unbound", true);
386
            break;
387
        case "unbound-control-setup":
388
            mwexec("echo '/usr/sbin/unbound-control-setup -d {$g['unbound_chroot_path']}' | /usr/bin/su -m unbound", true);
389
            break;
390
        default:
391
            break;
392
    }
393
}
394

    
395
function unbound_add_domain_overrides($pvt=false) {
396
    global $config, $g;
397

    
398
    $domains = $config['unbound']['domainoverrides'];
399

    
400
    $sorted_domains = msort($domains, "domain");
401
    $result = array();      
402
    foreach($sorted_domains as $domain) {
403
        $domain_key = current($domain);
404
        if (!isset($result[$domain_key]))
405
            $result[$domain_key] = array();
406
        $result[$domain_key][] = $domain['ip'];
407
    }
408

    
409
    // Domain overrides that have multiple entries need multiple stub-addr: added
410
    $domain_entries = "";
411
    foreach($result as $domain=>$ips) {
412
        if ($pvt == true) {
413
            $domain_entries .= "private-domain: \"$domain\"\n";
414
            $domain_entries .= "domain-insecure: \"$domain\"\n";
415
        } else {
416
            $domain_entries .= "stub-zone:\n";
417
            $domain_entries .= "\tname: \"$domain\"\n";
418
            foreach($ips as $ip)
419
                $domain_entries .= "\tstub-addr: $ip\n";
420
            $domain_entries .= "\tstub-prime: no\n";
421
        }
422
    }
423
    
424
    if ($pvt == true)
425
        return $domain_entries;
426
    else
427
        file_put_contents("{$g['unbound_chroot_path']}/domainoverrides.conf", $domain_entries);
428
}
429

    
430
function unbound_add_host_entries() {
431
    global $config, $g;
432

    
433
    $unbound_entries = "local-zone: \"{$config['system']['domain']}\" transparent\n";
434
    // IPv4 entries
435
    $unbound_entries .= "local-data-ptr: \"127.0.0.1 localhost\"\n";
436
    $unbound_entries .= "local-data: \"localhost A 127.0.0.1\"\n";
437
    $unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} A 127.0.0.1\"\n";
438
    // IPv6 entries
439
    $unbound_entries .= "local-data-ptr: \"::1 localhost\"\n";
440
    $unbound_entries .= "local-data: \"localhost AAAA ::1\"\n";
441
    $unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} AAAA ::1\"\n";
442

    
443
    $listen_addresses = "";
444
    if (isset($config['unbound']['interface'])) {
445
        $interfaces = explode(",", $config['unbound']['interface']);
446
        foreach ($interfaces as $interface) {
447
            if (is_ipaddrv4($interface)) {
448
                $unbound_entries .= "local-data-ptr: \"{$interface} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
449
                $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$interface}\"\n";
450
                $unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$interface}\"\n";
451
            } else if (is_ipaddrv6($interface)) {
452
                $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$interface}\"\n";
453
                $unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$interface}\"\n";
454
            } else {
455
                $if = get_real_interface($interface);
456
                if (does_interface_exist($if)) {
457
                    $laddr = find_interface_ip($if);
458
                    if (is_ipaddrv4($laddr)) {
459
                        $unbound_entries .= "local-data-ptr: \"{$laddr} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
460
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$laddr}\"\n";
461
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$laddr}\"\n";
462
                    }
463
                    $laddr6 = find_interface_ipv6($if);
464
                    if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
465
                        $unbound_entries .= "local-data-ptr: \"{$laddr6} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
466
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$laddr}\"\n";
467
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$laddr}\"\n";
468
                    }
469
                }
470
            }
471
        }
472
    }
473

    
474
    // Static Host entries
475
    if (isset($config['unbound']['hosts'])) {
476
        $host_entries = "";
477
        $added_item = array();
478
        foreach($config['unbound']['hosts'] as $host) {
479
            $current_host = $host['host'];
480
            if ($host['host'] != "")
481
                $host['host'] = $host['host'].".";
482
            if (!$added_item[$current_host]) {
483
                $host_entries .= "local-data-ptr: \"{$host['ip']} {$host['host']}{$host['domain']}\"\n";
484
                if (is_ipaddrv6($host['ip']))
485
                    $host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN AAAA {$host['ip']}\"\n";
486
                else
487
                    $host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN A {$host['ip']}\"\n";
488
                if (!empty($host['descr']) && $dnscfg['txtsupport'] == 'on')
489
                    $host_entries .= "local-data: '{$host['host']}{$host['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
490

    
491
                // Do not add duplicate entries
492
                $added_item[$current_host] = true;
493
            }
494
        }
495
        $unbound_entries .= $host_entries;
496
    }
497

    
498
    // Static DHCP entries
499
    $host_entries = "";
500
    if (isset($config['unbound']['regdhcpstatic']) && is_array($config['dhcpd'])) {
501
        foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf)
502
            if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable']))
503
                foreach ($dhcpifconf['staticmap'] as $host)
504
                    if ($host['ipaddr'] && $host['hostname']) {
505
                        $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['hostname']}.{$config['system']['domain']}\"\n";
506
                        $host_entries .= "local-data: \"{$host['hostname']}.{$config['system']['domain']} IN A {$host['ipaddr']}\"\n";
507
                        if (!empty($host['descr']) && $unboundcfg['txtsupport'] == 'on')
508
                            $host_entries .= "local-data: '{$host['hostname']}.{$config['system']['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
509
                    }
510
        $unbound_entries .= $host_entries;
511
    }
512

    
513
    // Handle DHCPLeases added host entries
514
    $dhcplcfg = read_hosts();
515
    $host_entries = "";
516
    if (is_array($dhcplcfg)) {
517
        foreach($dhcplcfg as $key=>$host) {
518
            $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['fqdn']}\"\n";
519
            $host_entries .= "local-data: \"{$host['fqdn']} IN A {$host['ipaddr']}\"\n";
520
            if (!empty($host['name'])) {
521
                $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['name']}\"\n";
522
                $host_entries .= "local-data: \"{$host['name']} IN A {$host['ipaddr']}\"\n";
523
            }
524
        }
525
        $unbound_entries .= $host_entries;
526
    }
527

    
528
    // Write out entries
529
    file_put_contents("{$g['unbound_chroot_path']}/host_entries.conf", $unbound_entries);
530
}
531

    
532
function unbound_control($action) {
533
    global $config, $g;
534

    
535
    $cache_dumpfile = "/var/tmp/unbound_cache";
536

    
537
    switch ($action) {
538
        case "start":
539
            // Start Unbound
540
            if ($config['unbound']['enable'] == "on") {
541
                if (!is_service_running("unbound"))
542
                    do_as_unbound_user("start");
543
            }
544
            break;
545
        case "stop":
546
            if ($config['unbound']['enable'] == "on")
547
                do_as_unbound_user("stop");
548
            break;
549
        case "dump_cache":
550
            // Dump Unbound's Cache
551
            if ($config['unbound']['dumpcache'] == "on")
552
                do_as_unbound_user("dump_cache");
553
            break;
554
        case "restore_cache":
555
            // Restore Unbound's Cache
556
            if ((is_service_running("unbound")) && ($config['unbound']['dumpcache'] == "on")) {
557
                if (file_exists($cache_dumpfile) && filesize($cache_dumpfile) > 0)
558
                    do_as_unbound_user("load_cache < /var/tmp/unbound_cache");
559
            }
560
            break;
561
        default:
562
                break;
563

    
564
        }
565
}
566

    
567
// Generation of Unbound statistics
568
function unbound_statistics() {
569
    global $config;
570

    
571
    if ($config['stats'] == "on") {
572
        $stats_interval = $config['unbound']['stats_interval'];
573
        $cumulative_stats = $config['cumulative_stats'];
574
        if ($config['extended_stats'] == "on")
575
            $extended_stats = "yes";
576
        else
577
            $extended_stats = "no";
578
    } else {
579
        $stats_interval = "0";
580
        $cumulative_stats = "no";
581
        $extended_stats = "no";
582
    }
583
    /* XXX To do - add RRD graphs */
584
    $stats = <<<EOF
585
# Unbound Statistics
586
statistics-interval: {$stats_interval}
587
extended-statistics: yes
588
statistics-cumulative: yes
589

    
590
EOF;
591

    
592
    return $stats;
593
}
594

    
595
// Unbound Access lists
596
function unbound_acls_config() {
597
    global $config;
598

    
599
    // Configure the ACLs
600
    if (is_array($config['unbound']['acls'])) {
601
        $unboundcfg = "";
602
        foreach($config['unbound']['acls'] as $unbound_acl) {
603
            $unboundcfg .= "#{$unbound_acl['aclname']}\n";
604
            foreach($unbound_acl['row'] as $network) {
605
                if ($unbound_acl['aclaction'] == "allow snoop")
606
                    $unbound_acl['aclaction'] = "allow_snoop";
607
                $unboundcfg .= "access-control: {$network['acl_network']}/{$network['mask']} {$unbound_acl['aclaction']}\n";
608
            }
609
        }
610
        // Write out Access list
611
        file_put_contents("{$g['unbound_chroot_path']}/access_lists.conf", $unboundcfg);
612
    } else
613
        return;
614
}
615

    
616
?>
(53-53/67)