Projet

Général

Profil

Télécharger (25,4 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / unbound.inc @ 31377265

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
    foreach ($config['sysctl']['item'] as $tunable) {
83
        if ($tunable['tunable'] == 'kern.ipc.maxsockbuf') {
84
            $so = floor(($tunable['value']/1024/1024)-1);
85
            // Check to ensure that the number is not a negative
86
            if ($so > 0)
87
                $optimization['so_rcvbuf'] = "so-rcvbuf: {$so}m";
88
            else
89
                unset($optimization['so_rcvbuf']);
90
        }
91
    }
92
    // Safety check in case kern.ipc.maxsockbuf is not available.
93
    if (!isset($optimization['so_rcvbuf']))
94
        $optimization['so_rcvbuf'] = "#so-rcvbuf: 4m";
95

    
96
    return $optimization;
97

    
98
}
99

    
100
function unbound_generate_config() {
101
    global $config, $g;
102

    
103
    // Setup optimization
104
    $optimization = unbound_optimization();
105

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

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

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

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

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

    
165
    // Configure static Host entries
166
    unbound_add_host_entries();
167

    
168
    // Configure Domain Overrides
169
    unbound_add_domain_overrides();
170

    
171
    // Configure Unbound statistics
172
    $statistics = unbound_statistics();
173

    
174
    // Configure Unbound access-lists
175
    unbound_acls_config();
176

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

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

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

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

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

    
235
    $unboundconf = <<<EOD
236
##########################
237
# Unbound Configuration
238
##########################
239

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

    
288
# DNS Rebinding
289
{$private_addr}
290
{$private_domains}
291

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

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

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

    
302
{$custom_options}
303

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

    
309
EOD;
310

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

    
313
    return 0;
314
}
315

    
316
function unbound_remote_control_setup() {
317
    global $g;
318

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

    
330
EOF;
331

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

    
334
        // Generate our keys
335
        do_as_unbound_user("unbound-control-setup");
336

    
337
    }
338
}
339

    
340

    
341
// Read /etc/hosts
342
function read_hosts() {
343

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

    
367
function sync_unbound_service() {
368
    global $config, $g;
369

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

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

    
386
}
387

    
388
function unbound_acl_id_used($id) {
389
    global $config;
390

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

    
396
    return false;
397
}
398

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

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

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

    
428
function unbound_add_domain_overrides($pvt=false) {
429
    global $config, $g;
430

    
431
    $domains = $config['unbound']['domainoverrides'];
432

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

    
442
    // Domain overrides that have multiple entries need multiple stub-addr: added
443
    $domain_entries = "";
444
    foreach($result as $domain=>$ips) {
445
        if ($pvt == true) {
446
            $domain_entries .= "private-domain: \"$domain\"\n";
447
            $domain_entries .= "domain-insecure: \"$domain\"\n";
448
        } else {
449
            $domain_entries .= "stub-zone:\n";
450
            $domain_entries .= "\tname: \"$domain\"\n";
451
            foreach($ips as $ip)
452
                $domain_entries .= "\tstub-addr: $ip\n";
453
            $domain_entries .= "\tstub-prime: no\n";
454
        }
455
    }
456
    
457
    if ($pvt == true)
458
        return $domain_entries;
459
    else
460
        file_put_contents("{$g['unbound_chroot_path']}/domainoverrides.conf", $domain_entries);
461
}
462

    
463
function unbound_add_host_entries() {
464
    global $config, $g;
465

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

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

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

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

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

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

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

    
565
function unbound_control($action) {
566
    global $config, $g;
567

    
568
    $cache_dumpfile = "/var/tmp/unbound_cache";
569

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

    
601
        }
602
}
603

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

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

    
627
EOF;
628

    
629
    return $stats;
630
}
631

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

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

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

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

    
674
}
675

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

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

    
685
?>
(54-54/68)