Project

General

Profile

Download (23 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
    unbound.inc
4
    part of the pfSense project (http://www.pfsense.com)
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
    $hide_id = ($config['unbound']['hide_id'] == "on") ? "yes" : "no";
156
    $hide_version = ($config['unbound']['hide_version'] == "on") ? "yes" : "no";
157
    $harden_glue = ($config['unbound']['harden_glue'] == "on") ? "yes" : "no";
158
    $harden_dnssec_stripped = ($config['unbound']['harden_dnssec_stripped'] == "on") ? "yes" : "no";
159
    $prefetch = ($config['unbound']['prefetch'] == "on") ? "yes" : "no";
160
    $prefetch_key = ($config['unbound']['prefetch_key'] == "on") ? "yes" : "no";
161
    $outgoing_num_tcp = (!empty($config['unbound']['outgoing_num_tcp'])) ? $config['unbound']['outgoing_num_tcp'] : "10";
162
    $incoming_num_tcp = (!empty($config['unbound']['incoming_num_tcp'])) ? $config['unbound']['incoming_num_tcp'] : "10";
163
    $edns_buffer_size = (!empty($config['unbound']['edns_buffer_size'])) ? $config['unbound']['edns_buffer_size'] : "4096";
164
    $num_queries_per_thread = (!empty($config['unbound']['num_queries_per_thread'])) ? $config['unbound']['num_queries_per_thread'] : "4096";
165
    $jostle_timeout = (!empty($config['unbound']['jostle_timeout'])) ? $config['unbound']['jostle_timeout'] : "200";
166
    $cache_max_ttl = (!empty($config['unbound']['cache_max_ttl'])) ? $config['unbound']['cache_max_ttl'] : "86400";
167
    $cache_min_ttl = (!empty($config['unbound']['cache_min_ttl'])) ? $config['unbound']['cache_min_ttl'] : "0";
168
    $infra_host_ttl = (!empty($config['unbound']['infra_host_ttl'])) ? $config['unbound']['infra_host_ttl'] : "900";
169
    $infra_lame_ttl = (!empty($config['unbound']['infra_lame_ttl'])) ? $config['unbound']['infra_lame_ttl'] : "900";
170
    $infra_cache_numhosts = (!empty($config['unbound']['infra_cache_numhosts'])) ? $config['unbound']['infra_cache_numhosts'] : "10000";
171
    $unwanted_reply_threshold = (!empty($config['unbound']['unwanted_reply_threshold'])) ? $config['unbound']['unwanted_reply_threshold'] : "0";
172
    $verbosity = isset($config['unbound']['loglevel']) ? $config['unbound']['loglevel'] : 1;
173

    
174
    $unboundconf = <<<EOD
175
##########################
176
# Unbound Configuration
177
##########################
178

    
179
##
180
# Server configuration
181
##
182
server:
183
chroot: {$g['unbound_chroot_path']}
184
username: "unbound"
185
directory: "{$g['unbound_chroot_path']}"
186
pidfile: "/var/run/unbound.pid"
187
use-syslog: yes
188
port: 53
189
verbosity: {$verbosity}
190
harden-referral-path: no
191
do-ip4: yes
192
do-ip6: yes
193
do-udp: yes
194
do-tcp: yes
195
do-daemonize: yes
196
module-config: "{$module_config}"
197
unwanted-reply-threshold: 0
198
num-queries-per-thread: 1024
199
jostle-timeout: 200
200
infra-host-ttl: 900
201
infra-lame-ttl: 900
202
infra-cache-numhosts: 10000
203
outgoing-num-tcp: 10
204
incoming-num-tcp: 10
205
edns-buffer-size: 4096
206
cache-max-ttl: {$cache_max_ttl}
207
cache-min-ttl: {$cache_min_ttl}
208
harden-dnssec-stripped: yes
209
{$optimization['number_threads']}
210
{$optimization['msg_cache_slabs']}
211
{$optimization['rrset_cache_slabs']}
212
{$optimization['infra_cache_slabs']}
213
{$optimization['key_cache_slabs']}
214
{$optimization['msg_cache_size']}
215
{$optimization['rrset_cache_size']}
216
{$optimization['outgoing_range']}
217
{$optimization['so_rcvbuf']}
218
{$anchor_file}
219
prefetch: {$prefetch}
220
prefetch-key: {$prefetch_key}
221
# Statistics
222
{$statistics}
223
# Interface IP(s) to bind to
224
interface: 0.0.0.0
225
interface: ::0
226

    
227
# DNS Rebinding
228
{$private_addr}
229
{$private_domains}
230

    
231
# Static host entries
232
include: {$g['unbound_chroot_path']}/host_entries.conf
233

    
234
# Domain overrides
235
include: {$g['unbound_chroot_path']}/domainoverrides.conf
236

    
237
{$custom_options}
238

    
239
###
240
# Remote Control Config
241
###
242
include: {$g['unbound_chroot_path']}/remotecontrol.conf
243

    
244
EOD;
245

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

    
248
    return 0;
249
}
250

    
251
function unbound_remote_control_setup() {
252
    global $g;
253

    
254
    if (!file_exists("{$g['unbound_chroot_path']}/remotecontrol.conf") || !file_exists("{$g['unbound_chroot_path']}/unbound_control.key")) {
255
        $remotcfg = <<<EOF
256
remote-control:
257
    control-enable: yes
258
    control-interface: 127.0.0.1
259
    control-port: 953
260
    server-key-file: "{$g['unbound_chroot_path']}/unbound_server.key"
261
    server-cert-file: "{$g['unbound_chroot_path']}/unbound_server.pem"
262
    control-key-file: "{$g['unbound_chroot_path']}/unbound_control.key"
263
    control-cert-file: "{$g['unbound_chroot_path']}/unbound_control.pem"
264

    
265
EOF;
266

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

    
269
        // Generate our keys
270
        do_as_unbound_user("unbound-control-setup");
271

    
272
    }
273
}
274

    
275

    
276
// Read /etc/hosts
277
function read_hosts() {
278

    
279
    /* Open /etc/hosts and extract the only dhcpleases info
280
     * XXX - to convert to an unbound C library which reads /etc/hosts automatically
281
     */
282
    $etc_hosts = array();
283
    foreach (file('/etc/hosts') as $line) {
284
        $d = preg_split('/\s/', $line, -1, PREG_SPLIT_NO_EMPTY);
285
        if (empty($d) || substr(reset($d), 0, 1) == "#")
286
            continue;
287
        if ($d[3] == "#") {
288
            $ip = array_shift($d);
289
            $fqdn = array_shift($d);
290
            $name = array_shift($d);
291
            if ($fqdn != "empty") {
292
                if ($name != "empty")
293
                    array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn", name => "$name"));
294
                else
295
                    array_push($etc_hosts, array(ipaddr => "$ip", fqdn => "$fqdn"));
296
            }
297
        }
298
    }
299
    return $etc_hosts;
300
}
301

    
302
function sync_unbound_service() {
303
    global $config, $g;
304

    
305
    // Configure chroot
306
    if (!is_dir($g['unbound_chroot_path'])) {
307
        mkdir($g['unbound_chroot_path']);
308
        chown($g['unbound_chroot_path'], "unbound");
309
        chgrp($g['unbound_chroot_path'], "unbound");
310
    }
311

    
312
    // Configure our Unbound service
313
    do_as_unbound_user("unbound-anchor");
314
    unbound_remote_control_setup();
315
    unbound_generate_config();
316
    do_as_unbound_user("start");
317
    require_once("service-utils.inc");
318
    if (is_service_running("unbound")) {
319
        do_as_unbound_user("forward");
320
        do_as_unbound_user("restore_cache");
321
    }
322

    
323
}
324

    
325
function unbound_acl_id_used($id) {
326
    global $config;
327

    
328
    if (is_array($config['unbound']['acls']))
329
        foreach($config['unbound']['acls'] as & $acls)
330
            if ($id == $acls['aclid'])
331
                return true;
332

    
333
    return false;
334
}
335

    
336
function unbound_get_next_id() {
337
    $aclid = 0;
338
    while(unbound_acl_id_used($aclid))
339
        $aclid++;
340
    return $aclid;
341
}
342

    
343
// Execute commands as the user unbound
344
function do_as_unbound_user($cmd) {
345
    global $g;
346

    
347
    switch ($cmd) {
348
        case "start":
349
            mwexec("/usr/sbin/unbound -c{$g['unbound_chroot_path']}/unbound.conf");
350
            break;
351
        case "stop":
352
            mwexec("echo '/usr/sbin/unbound-control stop' | /usr/bin/su -m unbound", true);
353
            break;
354
        case "unbound-anchor":
355
            mwexec("echo '/usr/sbin/unbound-anchor -a {$g['unbound_chroot_path']}/root.key' | /usr/bin/su -m unbound", true);
356
            break;
357
        case "unbound-control-setup":
358
            mwexec("echo '/usr/sbin/unbound-control-setup -d {$g['unbound_chroot_path']}' | /usr/bin/su -m unbound", true);
359
            break;
360
        default:
361
            break;
362
    }
363
}
364

    
365
function unbound_add_domain_overrides($pvt=false) {
366
    global $config, $g;
367

    
368
    $domains = $config['unbound']['domainoverrides'];
369

    
370
    $sorted_domains = msort($domains, "domain");
371
    $result = array();      
372
    foreach($sorted_domains as $domain) {
373
        $domain_key = current($domain);
374
        if (!isset($result[$domain_key]))
375
            $result[$domain_key] = array();
376
        $result[$domain_key][] = $domain['ip'];
377
    }
378

    
379
    // Domain overrides that have multiple entries need multiple stub-addr: added
380
    $domain_entries = "";
381
    foreach($result as $domain=>$ips) {
382
        if ($pvt == true) {
383
            $domain_entries .= "private-domain: \"$domain\"\n";
384
            $domain_entries .= "domain-insecure: \"$domain\"\n";
385
        } else {
386
            $domain_entries .= "stub-zone:\n";
387
            $domain_entries .= "\tname: \"$domain\"\n";
388
            foreach($ips as $ip)
389
                $domain_entries .= "\tstub-addr: $ip\n";
390
            $domain_entries .= "\tstub-prime: no\n";
391
        }
392
    }
393
    
394
    if ($pvt == true)
395
        return $domain_entries;
396
    else
397
        file_put_contents("{$g['unbound_chroot_path']}/domainoverrides.conf", $domain_entries);
398
}
399

    
400
function unbound_add_host_entries() {
401
    global $config, $g;
402

    
403
    $unbound_entries = "local-zone: \"{$config['system']['domain']}\" transparent\n";
404
    // IPv4 entries
405
    $unbound_entries .= "local-data-ptr: \"127.0.0.1 localhost\"\n";
406
    $unbound_entries .= "local-data: \"localhost A 127.0.0.1\"\n";
407
    $unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} A 127.0.0.1\"\n";
408
    // IPv6 entries
409
    $unbound_entries .= "local-data-ptr: \"::1 localhost\"\n";
410
    $unbound_entries .= "local-data: \"localhost AAAA ::1\"\n";
411
    $unbound_entries .= "local-data: \"localhost.{$config['system']['domain']} AAAA ::1\"\n";
412

    
413
    $listen_addresses = "";
414
    if (isset($config['unbound']['interface'])) {
415
        $interfaces = explode(",", $config['unbound']['interface']);
416
        foreach ($interfaces as $interface) {
417
            if (is_ipaddrv4($interface)) {
418
                $unbound_entries .= "local-data-ptr: \"{$interface} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
419
                $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$interface}\"\n";
420
                $unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$interface}\"\n";
421
            } else if (is_ipaddrv6($interface)) {
422
                $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$interface}\"\n";
423
                $unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$interface}\"\n";
424
            } else {
425
                $if = get_real_interface($interface);
426
                if (does_interface_exist($if)) {
427
                    $laddr = find_interface_ip($if);
428
                    if (is_ipaddrv4($laddr)) {
429
                        $unbound_entries .= "local-data-ptr: \"{$laddr} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
430
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} A {$laddr}\"\n";
431
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$laddr}\"\n";
432
                    }
433
                    $laddr6 = find_interface_ipv6($if);
434
                    if (is_ipaddrv6($laddr6) && !isset($config['dnsmasq']['strictbind'])) {
435
                        $unbound_entries .= "local-data-ptr: \"{$laddr6} {$config['system']['hostname']}.{$config['system']['domain']}\"\n";
436
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$config['system']['domain']} AAAA {$laddr}\"\n";
437
                        $unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$laddr}\"\n";
438
                    }
439
                }
440
            }
441
        }
442
    }
443

    
444
    // Static Host entries
445
    if (isset($config['unbound']['hosts'])) {
446
        $host_entries = "";
447
        $added_item = array();
448
        foreach($config['unbound']['hosts'] as $host) {
449
            $current_host = $host['host'];
450
            if ($host['host'] != "")
451
                $host['host'] = $host['host'].".";
452
            if (!$added_item[$current_host]) {
453
                $host_entries .= "local-data-ptr: \"{$host['ip']} {$host['host']}{$host['domain']}\"\n";
454
                if (is_ipaddrv6($host['ip']))
455
                    $host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN AAAA {$host['ip']}\"\n";
456
                else
457
                    $host_entries .= "local-data: \"{$host['host']}{$host['domain']} IN A {$host['ip']}\"\n";
458
                if (!empty($host['descr']) && $dnscfg['txtsupport'] == 'on')
459
                    $host_entries .= "local-data: '{$host['host']}{$host['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
460

    
461
                // Do not add duplicate entries
462
                $added_item[$current_host] = true;
463
            }
464
        }
465
        $unbound_entries .= $host_entries;
466
    }
467

    
468
    // Static DHCP entries
469
    $host_entries = "";
470
    if (isset($config['unbound']['regdhcpstatic']) && is_array($config['dhcpd'])) {
471
        foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf)
472
            if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable']))
473
                foreach ($dhcpifconf['staticmap'] as $host)
474
                    if ($host['ipaddr'] && $host['hostname']) {
475
                        $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['hostname']}.{$config['system']['domain']}\"\n";
476
                        $host_entries .= "local-data: \"{$host['hostname']}.{$config['system']['domain']} IN A {$host['ipaddr']}\"\n";
477
                        if (!empty($host['descr']) && $unboundcfg['txtsupport'] == 'on')
478
                            $host_entries .= "local-data: '{$host['hostname']}.{$config['system']['domain']} TXT \"".addslashes($host['descr'])."\"'\n";
479
                    }
480
        $unbound_entries .= $host_entries;
481
    }
482

    
483
    // Handle DHCPLeases added host entries
484
    $dhcplcfg = read_hosts();
485
    $host_entries = "";
486
    if (is_array($dhcplcfg)) {
487
        foreach($dhcplcfg as $key=>$host) {
488
            $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['fqdn']}\"\n";
489
            $host_entries .= "local-data: \"{$host['fqdn']} IN A {$host['ipaddr']}\"\n";
490
            if (!empty($host['name'])) {
491
                $host_entries .= "local-data-ptr: \"{$host['ipaddr']} {$host['name']}\"\n";
492
                $host_entries .= "local-data: \"{$host['name']} IN A {$host['ipaddr']}\"\n";
493
            }
494
        }
495
        $unbound_entries .= $host_entries;
496
    }
497

    
498
    // Write out entries
499
    file_put_contents("{$g['unbound_chroot_path']}/host_entries.conf", $unbound_entries);
500
}
501

    
502
function unbound_control($action) {
503
    global $config, $g;
504

    
505
    $cache_dumpfile = "/var/tmp/unbound_cache";
506

    
507
    switch ($action) {
508
        case "forward":
509
            if ($config['unbound']['forwarding_mode'] == "on") {
510
               // Get configured DNS servers and add them as forwarders
511
                if (!isset($config['system']['dnsallowoverride'])) {
512
                    $ns = array_unique(get_nameservers());
513
                    foreach($ns as $nameserver) {
514
                        if($nameserver)
515
                            $dns_servers .= " $nameserver";
516
                    }
517
                } else {
518
                    $ns = array_unique(get_dns_servers());
519
                    foreach($ns as $nameserver) {
520
                        if($nameserver)
521
                            $dns_servers .= " $nameserver";
522
                    }
523
                }
524

    
525
                if(is_service_running("unbound")) {
526
                    unbound_ctl_exec("forward $dns_servers");
527
                } else {
528
                    unbound_control("start");
529
                    sleep(1);
530
                    unbound_control("forward");
531
                }
532
            }
533
            break;
534
        case "start":
535
            // Start Unbound
536
            if ($config['unbound']['enable'] == "on") {
537
                if (!is_service_running("unbound"))
538
                    do_as_unbound_user("start");
539
            }
540
            break;
541
        case "stop":
542
            if ($config['unbound']['enable'] == "on")
543
                do_as_unbound_user("stop");
544
            break;
545
        case "dump_cache":
546
            // Dump Unbound's Cache
547
            if ($config['unbound']['dumpcache'] == "on")
548
                do_as_unbound_user("dump_cache");
549
            break;
550
        case "restore_cache":
551
            // Restore Unbound's Cache
552
            if ((is_service_running("unbound")) && ($config['unbound']['dumpcache'] == "on")) {
553
                if (file_exists($cache_dumpfile) && filesize($cache_dumpfile) > 0)
554
                    do_as_unbound_user("load_cache < /var/tmp/unbound_cache");
555
            }
556
            break;
557
        default:
558
                break;
559

    
560
        }
561
}
562

    
563
// Generation of Unbound statistics
564
function unbound_statistics() {
565
    global $config;
566

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

    
586
EOF;
587

    
588
    return $stats;
589
}
590

    
591
// Unbound Access lists
592
function unbound_acls_config() {
593
    global $config;
594

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

    
612
?>
(53-53/67)