mbox

new package: unbound 1.5.9

Message ID 1470163697-30802-2-git-send-email-marcel.lorenz@ipfire.org
State Superseded
Headers

Message

Marcel Lorenz Aug. 3, 2016, 4:48 a.m. UTC
  Unbound is a validating, recursive, and caching DNS resolver.
https://www.unbound.net

Signed-off-by: Marcel Lorenz <marcel.lorenz@ipfire.org>

---
 config/rootfiles/packages/unbound            |  70 ++++++++
 config/unbound/blocklists/ms-telemetry.conf  |  49 ++++++
 config/unbound/forward.conf                  |   6 +
 config/unbound/root.hints                    |  90 ++++++++++
 config/unbound/root.key                      |   9 +
 config/unbound/site-packages/daemonize.py    | 247 +++++++++++++++++++++++++++
 config/unbound/site-packages/dhcpd.py        | 108 ++++++++++++
 config/unbound/site-packages/params.py       |  46 +++++
 config/unbound/site-packages/watcherdhcpd.py | 107 ++++++++++++
 config/unbound/unbound-dhcpd.py              | 145 ++++++++++++++++
 config/unbound/unbound-switch                |  80 +++++++++
 config/unbound/unbound-zone                  |  78 +++++++++
 config/unbound/unbound.conf                  | 123 +++++++++++++
 lfs/unbound                                  | 103 +++++++++++
 make.sh                                      |   1 +
 src/initscripts/init.d/network-unbound       | 114 +++++++++++++
 src/initscripts/init.d/unbound               | 178 +++++++++++++++++++
 src/initscripts/init.d/unbound-dhcpd         |  61 +++++++
 src/paks/unbound/install.sh                  |  70 ++++++++
 src/paks/unbound/uninstall.sh                |  27 +++
 src/paks/unbound/update.sh                   |  26 +++
 21 files changed, 1738 insertions(+)
 create mode 100644 config/rootfiles/packages/unbound
 create mode 100644 config/unbound/blocklists/ms-telemetry.conf
 create mode 100644 config/unbound/forward.conf
 create mode 100644 config/unbound/root.hints
 create mode 100644 config/unbound/root.key
 create mode 100644 config/unbound/site-packages/daemonize.py
 create mode 100644 config/unbound/site-packages/dhcpd.py
 create mode 100644 config/unbound/site-packages/params.py
 create mode 100644 config/unbound/site-packages/watcherdhcpd.py
 create mode 100644 config/unbound/unbound-dhcpd.py
 create mode 100755 config/unbound/unbound-switch
 create mode 100644 config/unbound/unbound-zone
 create mode 100644 config/unbound/unbound.conf
 create mode 100644 lfs/unbound
 create mode 100644 src/initscripts/init.d/network-unbound
 create mode 100644 src/initscripts/init.d/unbound
 create mode 100644 src/initscripts/init.d/unbound-dhcpd
 create mode 100644 src/paks/unbound/install.sh
 create mode 100644 src/paks/unbound/uninstall.sh
 create mode 100644 src/paks/unbound/update.sh
  

Comments

Michael Tremer Aug. 7, 2016, 4:57 a.m. UTC | #1
Hi,

so I have been working on this for a bit over the weekend and started a branch
with those changes.

  http://cgit.ipfire.org/people/ms/ipfire-2.x.git/log/?h=unbound

I rewrote the Python code which I didn't find clean enough and good enough for
our standards. My solution is lacking some minor things (the domain is always
.local) but those should be easily fixable. I am just running out of time here.

However I wanted to share my changes for you to review and test because despite
these small things and some other issues for which I created bug reports on
Bugzilla, I think this is rather close to be finished.

  https://bugzilla.ipfire.org/showdependencytree.cgi?id=11163&hide_resolved=1

So, please have a look and test. I won't be able to work much on this over the
next few weeks, hence I would be happy if some people take over a small part and
get that fixed. I will be responding to emails though.

Best,
-Michael

On Tue, 2016-08-02 at 20:48 +0200, Marcel Lorenz wrote:
> Unbound is a validating, recursive, and caching DNS resolver.
> https://www.unbound.net
> 
> Signed-off-by: Marcel Lorenz <marcel.lorenz@ipfire.org>
> 
> ---
>  config/rootfiles/packages/unbound            |  70 ++++++++
>  config/unbound/blocklists/ms-telemetry.conf  |  49 ++++++
>  config/unbound/forward.conf                  |   6 +
>  config/unbound/root.hints                    |  90 ++++++++++
>  config/unbound/root.key                      |   9 +
>  config/unbound/site-packages/daemonize.py    | 247
> +++++++++++++++++++++++++++
>  config/unbound/site-packages/dhcpd.py        | 108 ++++++++++++
>  config/unbound/site-packages/params.py       |  46 +++++
>  config/unbound/site-packages/watcherdhcpd.py | 107 ++++++++++++
>  config/unbound/unbound-dhcpd.py              | 145 ++++++++++++++++
>  config/unbound/unbound-switch                |  80 +++++++++
>  config/unbound/unbound-zone                  |  78 +++++++++
>  config/unbound/unbound.conf                  | 123 +++++++++++++
>  lfs/unbound                                  | 103 +++++++++++
>  make.sh                                      |   1 +
>  src/initscripts/init.d/network-unbound       | 114 +++++++++++++
>  src/initscripts/init.d/unbound               | 178 +++++++++++++++++++
>  src/initscripts/init.d/unbound-dhcpd         |  61 +++++++
>  src/paks/unbound/install.sh                  |  70 ++++++++
>  src/paks/unbound/uninstall.sh                |  27 +++
>  src/paks/unbound/update.sh                   |  26 +++
>  21 files changed, 1738 insertions(+)
>  create mode 100644 config/rootfiles/packages/unbound
>  create mode 100644 config/unbound/blocklists/ms-telemetry.conf
>  create mode 100644 config/unbound/forward.conf
>  create mode 100644 config/unbound/root.hints
>  create mode 100644 config/unbound/root.key
>  create mode 100644 config/unbound/site-packages/daemonize.py
>  create mode 100644 config/unbound/site-packages/dhcpd.py
>  create mode 100644 config/unbound/site-packages/params.py
>  create mode 100644 config/unbound/site-packages/watcherdhcpd.py
>  create mode 100644 config/unbound/unbound-dhcpd.py
>  create mode 100755 config/unbound/unbound-switch
>  create mode 100644 config/unbound/unbound-zone
>  create mode 100644 config/unbound/unbound.conf
>  create mode 100644 lfs/unbound
>  create mode 100644 src/initscripts/init.d/network-unbound
>  create mode 100644 src/initscripts/init.d/unbound
>  create mode 100644 src/initscripts/init.d/unbound-dhcpd
>  create mode 100644 src/paks/unbound/install.sh
>  create mode 100644 src/paks/unbound/uninstall.sh
>  create mode 100644 src/paks/unbound/update.sh
> 
> diff --git a/config/rootfiles/packages/unbound
> b/config/rootfiles/packages/unbound
> new file mode 100644
> index 0000000..c468167
> --- /dev/null
> +++ b/config/rootfiles/packages/unbound
> @@ -0,0 +1,70 @@
> +etc/rc.d/init.d/network-unbound
> +etc/rc.d/init.d/unbound
> +etc/rc.d/init.d/unbound-dhcpd
> +#etc/unbound
> +#etc/unbound/blocklists
> +etc/unbound/blocklists/ms-telemetry.conf
> +etc/unbound/forward.conf
> +etc/unbound/root.hints
> +etc/unbound/root.key
> +etc/unbound/unbound.conf
> +etc/unbound/unbound_org.conf
> +usr/bin/unbound-host
> +#usr/include/unbound.h
> +#usr/lib/libunbound.la
> +usr/lib/libunbound.so
> +usr/lib/libunbound.so.2
> +usr/lib/libunbound.so.2.4.1
> +#usr/lib/python2.7/site-packages/_unbound.la
> +usr/lib/python2.7/site-packages/_unbound.so
> +usr/lib/python2.7/site-packages/daemonize.py
> +usr/lib/python2.7/site-packages/dhcpd.py
> +usr/lib/python2.7/site-packages/params.py
> +usr/lib/python2.7/site-packages/unbound.py
> +usr/lib/python2.7/site-packages/watcherdhcpd.py
> +usr/sbin/unbound
> +usr/sbin/unbound-anchor
> +usr/sbin/unbound-checkconf
> +usr/sbin/unbound-dhcpd.py
> +usr/sbin/unbound-control
> +usr/sbin/unbound-control-setup
> +usr/sbin/unbound-switch
> +usr/sbin/unbound-zone
> +#usr/share/man/man1/unbound-host.1
> +#usr/share/man/man3/libunbound.3
> +#usr/share/man/man3/ub_cancel.3
> +#usr/share/man/man3/ub_ctx.3
> +#usr/share/man/man3/ub_ctx_add_ta.3
> +#usr/share/man/man3/ub_ctx_add_ta_file.3
> +#usr/share/man/man3/ub_ctx_async.3
> +#usr/share/man/man3/ub_ctx_config.3
> +#usr/share/man/man3/ub_ctx_create.3
> +#usr/share/man/man3/ub_ctx_data_add.3
> +#usr/share/man/man3/ub_ctx_data_remove.3
> +#usr/share/man/man3/ub_ctx_debuglevel.3
> +#usr/share/man/man3/ub_ctx_debugout.3
> +#usr/share/man/man3/ub_ctx_delete.3
> +#usr/share/man/man3/ub_ctx_get_option.3
> +#usr/share/man/man3/ub_ctx_hosts.3
> +#usr/share/man/man3/ub_ctx_print_local_zones.3
> +#usr/share/man/man3/ub_ctx_resolvconf.3
> +#usr/share/man/man3/ub_ctx_set_fwd.3
> +#usr/share/man/man3/ub_ctx_set_option.3
> +#usr/share/man/man3/ub_ctx_trustedkeys.3
> +#usr/share/man/man3/ub_ctx_zone_add.3
> +#usr/share/man/man3/ub_ctx_zone_remove.3
> +#usr/share/man/man3/ub_fd.3
> +#usr/share/man/man3/ub_poll.3
> +#usr/share/man/man3/ub_process.3
> +#usr/share/man/man3/ub_resolve.3
> +#usr/share/man/man3/ub_resolve_async.3
> +#usr/share/man/man3/ub_resolve_free.3
> +#usr/share/man/man3/ub_result.3
> +#usr/share/man/man3/ub_strerror.3
> +#usr/share/man/man3/ub_wait.3
> +#usr/share/man/man5/unbound.conf.5
> +#usr/share/man/man8/unbound-anchor.8
> +#usr/share/man/man8/unbound-checkconf.8
> +#usr/share/man/man8/unbound-control-setup.8
> +#usr/share/man/man8/unbound-control.8
> +#usr/share/man/man8/unbound.8
> diff --git a/config/unbound/blocklists/ms-telemetry.conf
> b/config/unbound/blocklists/ms-telemetry.conf
> new file mode 100644
> index 0000000..7801e76
> --- /dev/null
> +++ b/config/unbound/blocklists/ms-telemetry.conf
> @@ -0,0 +1,49 @@
> +# Windows telemetry
> +local-data: "a-0001.a-msedge.net A 127.0.0.1"
> +local-data: "asimov-win.settings.data.microsoft.com.akadns.net. A 127.0.0.1"
> +local-data: "asimov-win.vortex.data.microsoft.com.akadns.net. A 127.0.0.1"
> +local-data: "choice.microsoft.com A 127.0.0.1"
> +local-data: "choice.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "compatexchange.cloudapp.net A 127.0.0.1"
> +local-data: "corpext.msitadfs.glbdns2.microsoft.com A 127.0.0.1"
> +local-data: "corp.sts.microsoft.com A 127.0.0.1"
> +local-data: "cs1.wpc.v0cdn.net A 127.0.0.1"
> +local-data: "df.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "diagnostics.support.microsoft.com A 127.0.0.1"
> +local-data: "fe2.update.microsoft.com.akadns.net A 127.0.0.1"
> +local-data: "feedback.microsoft-hohm.com A 127.0.0.1"
> +local-data: "feedback.search.microsoft.com A 127.0.0.1"
> +local-data: "feedback.windows.com A 127.0.0.1"
> +local-data: "i1.services.social.microsoft.com A 127.0.0.1"
> +local-data: "i1.services.social.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "nexus.officeapps.live.com A 127.0.0.1"
> +local-data: "oca.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "oca.telemetry.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "pre.footprintpredict.com A 127.0.0.1"
> +local-data: "redir.metaservices.microsoft.com A 127.0.0.1"
> +local-data: "reports.wes.df.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "services.wes.df.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "settings-sandbox.data.microsoft.com A 127.0.0.1"
> +local-data: "settings-win.data.microsoft.com A 127.0.0.1"
> +local-data: "sls.update.microsoft.com.akadns.net A 127.0.0.1"
> +local-data: "sqm.df.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "sqm.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "sqm.telemetry.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "statsfe1.ws.microsoft.com A 127.0.0.1"
> +local-data: "statsfe2.update.microsoft.com.akadns.net A 127.0.0.1"
> +local-data: "statsfe2.ws.microsoft.com A 127.0.0.1"
> +local-data: "survey.watson.microsoft.com A 127.0.0.1"
> +local-data: "telecommand.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "telecommand.telemetry.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "telemetry.appex.bing.net A 127.0.0.1"
> +local-data: "telemetry.microsoft.com A 127.0.0.1"
> +local-data: "telemetry.urs.microsoft.com A 127.0.0.1"
> +local-data: "vortex.data.microsoft.com A 127.0.0.1"
> +local-data: "vortex-sandbox.data.microsoft.com A 127.0.0.1"
> +local-data: "vortex-win.data.microsoft.com  A 127.0.0.1"
> +local-data: "watson.live.com A 127.0.0.1"
> +local-data: "watson.microsoft.com A 127.0.0.1"
> +local-data: "watson.ppe.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "watson.telemetry.microsoft.com A 127.0.0.1"
> +local-data: "watson.telemetry.microsoft.com.nsatc.net A 127.0.0.1"
> +local-data: "wes.df.telemetry.microsoft.com A 127.0.0.1"
> diff --git a/config/unbound/forward.conf b/config/unbound/forward.conf
> new file mode 100644
> index 0000000..5784f9f
> --- /dev/null
> +++ b/config/unbound/forward.conf
> @@ -0,0 +1,6 @@
> +forward-zone:
> +  name: "."
> +  forward-addr: 85.214.20.141
> +  forward-addr: 194.150.168.168
> +  forward-addr: 208.67.222.222
> +  forward-addr: 208.67.220.220
> diff --git a/config/unbound/root.hints b/config/unbound/root.hints
> new file mode 100644
> index 0000000..3c82146
> --- /dev/null
> +++ b/config/unbound/root.hints
> @@ -0,0 +1,90 @@
> +;       This file holds the information on root name servers needed to
> +;       initialize cache of Internet domain name servers
> +;       (e.g. reference this file in the "cache  .  <file>"
> +;       configuration file of BIND domain name servers).
> +;
> +;       This file is made available by InterNIC 
> +;       under anonymous FTP as
> +;           file                /domain/named.cache
> +;           on server           FTP.INTERNIC.NET
> +;       -OR-                    RS.INTERNIC.NET
> +;
> +;       last update:    March 23, 2016
> +;       related version of root zone:   2016032301
> +;
> +; formerly NS.INTERNIC.NET
> +;
> +.                        3600000      NS    A.ROOT-SERVERS.NET.
> +A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
> +A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
> +;
> +; FORMERLY NS1.ISI.EDU
> +;
> +.                        3600000      NS    B.ROOT-SERVERS.NET.
> +B.ROOT-SERVERS.NET.      3600000      A     192.228.79.201
> +B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:84::b
> +;
> +; FORMERLY C.PSI.NET
> +;
> +.                        3600000      NS    C.ROOT-SERVERS.NET.
> +C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
> +C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
> +;
> +; FORMERLY TERP.UMD.EDU
> +;
> +.                        3600000      NS    D.ROOT-SERVERS.NET.
> +D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
> +D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
> +;
> +; FORMERLY NS.NASA.GOV
> +;
> +.                        3600000      NS    E.ROOT-SERVERS.NET.
> +E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
> +;
> +; FORMERLY NS.ISC.ORG
> +;
> +.                        3600000      NS    F.ROOT-SERVERS.NET.
> +F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
> +F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
> +;
> +; FORMERLY NS.NIC.DDN.MIL
> +;
> +.                        3600000      NS    G.ROOT-SERVERS.NET.
> +G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
> +;
> +; FORMERLY AOS.ARL.ARMY.MIL
> +;
> +.                        3600000      NS    H.ROOT-SERVERS.NET.
> +H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
> +H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
> +;
> +; FORMERLY NIC.NORDU.NET
> +;
> +.                        3600000      NS    I.ROOT-SERVERS.NET.
> +I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
> +I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
> +;
> +; OPERATED BY VERISIGN, INC.
> +;
> +.                        3600000      NS    J.ROOT-SERVERS.NET.
> +J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
> +J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
> +;
> +; OPERATED BY RIPE NCC
> +;
> +.                        3600000      NS    K.ROOT-SERVERS.NET.
> +K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
> +K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
> +;
> +; OPERATED BY ICANN
> +;
> +.                        3600000      NS    L.ROOT-SERVERS.NET.
> +L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
> +L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
> +;
> +; OPERATED BY WIDE
> +;
> +.                        3600000      NS    M.ROOT-SERVERS.NET.
> +M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
> +M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
> +; End of file
> diff --git a/config/unbound/root.key b/config/unbound/root.key
> new file mode 100644
> index 0000000..fb540e3
> --- /dev/null
> +++ b/config/unbound/root.key
> @@ -0,0 +1,9 @@
> +; autotrust trust anchor file
> +;;id: . 1
> +;;last_queried: 1467576595 ;;Sun Jul  3 22:09:55 2016
> +;;last_success: 1467576595 ;;Sun Jul  3 22:09:55 2016
> +;;next_probe_time: 1467616562 ;;Mon Jul  4 09:16:02 2016
> +;;query_failed: 0
> +;;query_interval: 43200
> +;;retry_time: 8640
> +.	172800	IN	DNSKEY	257 3 8
> AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0Ez
> rAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkj
> f5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCT
> MjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqr
> AmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= ;{id = 19036 (ksk), size = 2048b}
> ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1467575383 ;;Sun Jul  3 21:49:43
> 2016
> diff --git a/config/unbound/site-packages/daemonize.py b/config/unbound/site-
> packages/daemonize.py
> new file mode 100644
> index 0000000..e083feb
> --- /dev/null
> +++ b/config/unbound/site-packages/daemonize.py
> @@ -0,0 +1,247 @@
> +# #!/usr/bin/python
> +
> +import fcntl
> +import os
> +import pwd
> +import grp
> +import sys
> +import signal
> +import resource
> +import logging
> +import atexit
> +from logging import handlers
> +import traceback
> +
> +
> +__version__ = "2.4.6"
> +
> +
> +class Daemonize(object):
> +    """
> +    Daemonize object.
> +
> +    Object constructor expects three arguments.
> +
> +    :param app: contains the application name which will be sent to syslog.
> +    :param pid: path to the pidfile.
> +    :param action: your custom function which will be executed after
> daemonization.
> +    :param keep_fds: optional list of fds which should not be closed.
> +    :param auto_close_fds: optional parameter to not close opened fds.
> +    :param privileged_action: action that will be executed before drop
> privileges if user or
> +                              group parameter is provided.
> +                              If you want to transfer anything from
> privileged_action to action, such as
> +                              opened privileged file descriptor, you should
> return it from
> +                              privileged_action function and catch it inside
> action function.
> +    :param user: drop privileges to this user if provided.
> +    :param group: drop privileges to this group if provided.
> +    :param verbose: send debug messages to logger if provided.
> +    :param logger: use this logger object instead of creating new one, if
> provided.
> +    :param foreground: stay in foreground; do not fork (for debugging)
> +    :param chdir: change working directory if provided or /
> +    """
> +    def __init__(self, app, pid, action,
> +                 keep_fds=None, auto_close_fds=True, privileged_action=None,
> +                 user=None, group=None, verbose=False, logger=None,
> +                 foreground=False, chdir="/"):
> +        self.app = app
> +        self.pid = os.path.abspath(pid)
> +        self.action = action
> +        self.keep_fds = keep_fds or []
> +        self.privileged_action = privileged_action or (lambda: ())
> +        self.user = user
> +        self.group = group
> +        self.logger = logger
> +        self.verbose = verbose
> +        self.auto_close_fds = auto_close_fds
> +        self.foreground = foreground
> +        self.chdir = chdir
> +
> +    def sigterm(self, signum, frame):
> +        """
> +        These actions will be done after SIGTERM.
> +        """
> +        self.logger.warn("Caught signal %s. Stopping daemon." % signum)
> +        sys.exit(0)
> +
> +    def exit(self):
> +        """
> +        Cleanup pid file at exit.
> +        """
> +        self.logger.warn("Stopping daemon.")
> +        os.remove(self.pid)
> +        sys.exit(0)
> +
> +    def start(self):
> +        """
> +        Start daemonization process.
> +        """
> +        # If pidfile already exists, we should read pid from there; to
> overwrite it, if locking
> +        # will fail, because locking attempt somehow purges the file
> contents.
> +        if os.path.isfile(self.pid):
> +            with open(self.pid, "r") as old_pidfile:
> +                old_pid = old_pidfile.read()
> +        # Create a lockfile so that only one instance of this daemon is
> running at any time.
> +        try:
> +            lockfile = open(self.pid, "w")
> +        except IOError:
> +            print("Unable to create the pidfile.")
> +            sys.exit(1)
> +        try:
> +            # Try to get an exclusive lock on the file. This will fail if
> another process has the file
> +            # locked.
> +            fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
> +        except IOError:
> +            print("Unable to lock on the pidfile.")
> +            # We need to overwrite the pidfile if we got here.
> +            with open(self.pid, "w") as pidfile:
> +                pidfile.write(old_pid)
> +            sys.exit(1)
> +
> +        # skip fork if foreground is specified
> +        if not self.foreground:
> +            # Fork, creating a new process for the child.
> +            try:
> +                process_id = os.fork()
> +            except OSError as e:
> +                self.logger.error("Unable to fork, errno:
> {0}".format(e.errno))
> +                sys.exit(1)
> +            if process_id != 0:
> +                # This is the parent process. Exit without cleanup,
> +                # see https://github.com/thesharp/daemonize/issues/46
> +                os._exit(0)
> +            # This is the child process. Continue.
> +
> +            # Stop listening for signals that the parent process receives.
> +            # This is done by getting a new process id.
> +            # setpgrp() is an alternative to setsid().
> +            # setsid puts the process in a new parent group and detaches its
> controlling terminal.
> +            process_id = os.setsid()
> +            if process_id == -1:
> +                # Uh oh, there was a problem.
> +                sys.exit(1)
> +
> +            # Add lockfile to self.keep_fds.
> +            self.keep_fds.append(lockfile.fileno())
> +
> +            # Close all file descriptors, except the ones mentioned in
> self.keep_fds.
> +            devnull = "/dev/null"
> +            if hasattr(os, "devnull"):
> +                # Python has set os.devnull on this system, use it instead as
> it might be different
> +                # than /dev/null.
> +                devnull = os.devnull
> +
> +            if self.auto_close_fds:
> +                for fd in range(3,
> resource.getrlimit(resource.RLIMIT_NOFILE)[0]):
> +                    if fd not in self.keep_fds:
> +                        try:
> +                            os.close(fd)
> +                        except OSError:
> +                            pass
> +
> +            devnull_fd = os.open(devnull, os.O_RDWR)
> +            os.dup2(devnull_fd, 0)
> +            os.dup2(devnull_fd, 1)
> +            os.dup2(devnull_fd, 2)
> +
> +        if self.logger is None:
> +            # Initialize logging.
> +            self.logger = logging.getLogger(self.app)
> +            self.logger.setLevel(logging.DEBUG)
> +            # Display log messages only on defined handlers.
> +            self.logger.propagate = False
> +
> +            # Initialize syslog.
> +            # It will correctly work on OS X, Linux and FreeBSD.
> +            if sys.platform == "darwin":
> +                syslog_address = "/var/run/syslog"
> +            else:
> +                syslog_address = "/dev/log"
> +
> +            # We will continue with syslog initialization only if actually
> have such capabilities
> +            # on the machine we are running this.
> +            if os.path.exists(syslog_address):
> +                syslog = handlers.SysLogHandler(syslog_address)
> +                if self.verbose:
> +                    syslog.setLevel(logging.DEBUG)
> +                else:
> +                    syslog.setLevel(logging.INFO)
> +                # Try to mimic to normal syslog messages.
> +                formatter = logging.Formatter("%(asctime)s %(name)s:
> %(message)s",
> +                                              "%b %e %H:%M:%S")
> +                syslog.setFormatter(formatter)
> +
> +                self.logger.addHandler(syslog)
> +
> +        # Set umask to default to safe file permissions when running as a
> root daemon. 027 is an
> +        # octal number which we are typing as 0o27 for Python3 compatibility.
> +        os.umask(0o27)
> +
> +        # Change to a known directory. If this isn't done, starting a daemon
> in a subdirectory that
> +        # needs to be deleted results in "directory busy" errors.
> +        os.chdir(self.chdir)
> +
> +        # Execute privileged action
> +        privileged_action_result = self.privileged_action()
> +        if not privileged_action_result:
> +            privileged_action_result = []
> +
> +        # Change owner of pid file, it's required because pid file will be
> removed at exit.
> +        uid, gid = -1, -1
> +
> +        if self.group:
> +            try:
> +                gid = grp.getgrnam(self.group).gr_gid
> +            except KeyError:
> +                self.logger.error("Group {0} not found".format(self.group))
> +                sys.exit(1)
> +
> +        if self.user:
> +            try:
> +                uid = pwd.getpwnam(self.user).pw_uid
> +            except KeyError:
> +                self.logger.error("User {0} not found.".format(self.user))
> +                sys.exit(1)
> +
> +        if uid != -1 or gid != -1:
> +            os.chown(self.pid, uid, gid)
> +
> +        # Change gid
> +        if self.group:
> +            try:
> +                os.setgid(gid)
> +            except OSError:
> +                self.logger.error("Unable to change gid.")
> +                sys.exit(1)
> +
> +        # Change uid
> +        if self.user:
> +            try:
> +                uid = pwd.getpwnam(self.user).pw_uid
> +            except KeyError:
> +                self.logger.error("User {0} not found.".format(self.user))
> +                sys.exit(1)
> +            try:
> +                os.setuid(uid)
> +            except OSError:
> +                self.logger.error("Unable to change uid.")
> +                sys.exit(1)
> +
> +        try:
> +            lockfile.write("%s" % (os.getpid()))
> +            lockfile.flush()
> +        except IOError:
> +            self.logger.error("Unable to write pid to the pidfile.")
> +            print("Unable to write pid to the pidfile.")
> +            sys.exit(1)
> +
> +        # Set custom action on SIGTERM.
> +        signal.signal(signal.SIGTERM, self.sigterm)
> +        atexit.register(self.exit)
> +
> +        self.logger.warn("Starting daemon.")
> +
> +        try:
> +            self.action(*privileged_action_result)
> +        except Exception as e:
> +            for line in traceback.format_exc(e).split("\n"):
> +                self.logger.error(line)
> diff --git a/config/unbound/site-packages/dhcpd.py b/config/unbound/site-
> packages/dhcpd.py
> new file mode 100644
> index 0000000..6d586c7
> --- /dev/null
> +++ b/config/unbound/site-packages/dhcpd.py
> @@ -0,0 +1,108 @@
> +"""
> +    Copyright (c) 2016 Ad Schellevis
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions are
> met:
> +
> +    1. Redistributions of source code must retain the above copyright notice,
> +     this list of conditions and the following disclaimer.
> +
> +    2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> WARRANTIES,
> +    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> +    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> THE
> +    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> EXEMPLARY,
> +    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> +    POSSIBILITY OF SUCH DAMAGE.
> +"""
> +import os
> +import time
> +import datetime
> +
> +class DHCPDLease(object):
> +    watch_file = '/var/dhcpd/var/db/dhcpd.leases'
> +
> +    def __init__(self):
> +        """ init watcher
> +        :return: watcher object
> +        """
> +        self._section_data = []
> +        self._fhandle = None
> +        self._last_pos = None
> +        self._open()
> +
> +    def _open(self):
> +        """ (re)open watched file
> +        :return: watcher object
> +        """
> +        try:
> +            self._fhandle = open(self.watch_file, 'r')
> +            self._last_pos = None
> +            self._section_data = []
> +            return True
> +        except IOError:
> +            self._fhandle = None
> +            return False
> +
> +    @staticmethod
> +    def parse_lease(lines):
> +        """ parse dhcp lease
> +        :param lines: lease section as list item
> +        :return: dictionary
> +        """
> +        lease = dict()
> +        lease['address'] = lines[0].split()[1]
> +        for line in lines:
> +            parts =  line.split()
> +            field_name = parts[0]
> +            field_value = None
> +            if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp',
> 'cltt') and len(parts) >= 3:
> +                dt = '%s %s'%(parts[2], parts[3])
> +                try:
> +                    field_value = time.mktime(datetime.datetime.strptime(dt,
> "%Y/%m/%d %H:%M:%S;").timetuple())
> +                except ValueError:
> +                    field_value = None
> +            elif field_name == 'hardware' and len(parts) >= 3:
> +                field_value = {'hardware-type': parts[1], 'mac-address':
> parts[2]}
> +            elif field_name in('uid', 'client-hostname') and len(parts) >= 2
> and parts[1].find('"') > -1:
> +                field_value = parts[1].split('"')[1]
> +
> +            if field_value is not None:
> +                lease[field_name] = field_value
> +
> +        return lease
> +
> +    def watch(self):
> +        """ watch file, return lease dictionaries
> +        :return: iterator for leases
> +        """
> +        if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink
> == 0:
> +            # nothing to watch, try to (re)open return when failed
> +            if not self._open():
> +                return
> +        elif self._last_pos is not None:
> +            self._fhandle.seek(self._last_pos)
> +
> +        while True:
> +            line = self._fhandle.readline()
> +            if line:
> +                if len(line) > 5 and line[0:5] == 'lease':
> +                    self._section_data.append(line)
> +                elif len(line) > 1 and line[0] == '}':
> +                    self._section_data.append(line)
> +                    yield self.parse_lease(self._section_data)
> +                    self._section_data = []
> +                elif len(self._section_data) > 0:
> +                    self._section_data.append(line)
> +            else:
> +                break
> +
> +        self._last_pos = self._fhandle.tell()
> diff --git a/config/unbound/site-packages/params.py b/config/unbound/site-
> packages/params.py
> new file mode 100644
> index 0000000..6be3244
> --- /dev/null
> +++ b/config/unbound/site-packages/params.py
> @@ -0,0 +1,46 @@
> +"""
> +    Copyright (c) 2015-2016 Ad Schellevis
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions are
> met:
> +
> +    1. Redistributions of source code must retain the above copyright notice,
> +     this list of conditions and the following disclaimer.
> +
> +    2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> WARRANTIES,
> +    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> +    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> THE
> +    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> EXEMPLARY,
> +    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> +    POSSIBILITY OF SUCH DAMAGE.
> +"""
> +
> +import sys
> +
> +
> +def update_params(parameters):
> +    """ update predefined parameters with given list from shell (as switches)
> +        for example /a valA /b valB
> +        converts to
> +            {'a':'valA','b':'valB'}
> +        (assuming parameters contains both a and b)
> +    :param parameters: parameter dictionary
> +    :return:
> +    """
> +    cmd = None
> +    for arg in sys.argv[1:]:
> +        if cmd is None:
> +            cmd = arg[1:]
> +        else:
> +            if cmd in parameters and arg.strip() != '':
> +                parameters[cmd] = arg.strip()
> +            cmd = None
> diff --git a/config/unbound/site-packages/watcherdhcpd.py
> b/config/unbound/site-packages/watcherdhcpd.py
> new file mode 100644
> index 0000000..c726d5c
> --- /dev/null
> +++ b/config/unbound/site-packages/watcherdhcpd.py
> @@ -0,0 +1,107 @@
> +"""
> +    Copyright (c) 2016 Ad Schellevis
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions are
> met:
> +
> +    1. Redistributions of source code must retain the above copyright notice,
> +     this list of conditions and the following disclaimer.
> +
> +    2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> WARRANTIES,
> +    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> +    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> THE
> +    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> EXEMPLARY,
> +    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> +    POSSIBILITY OF SUCH DAMAGE.
> +"""
> +import os
> +import time
> +import datetime
> +
> +class DHCPDLease(object):
> +    watch_file = '/var/state/dhcp/dhcpd.leases'
> +
> +    def __init__(self):
> +        """ init watcher
> +        :return: watcher object
> +        """
> +        self._section_data = []
> +        self._fhandle = None
> +        self._last_pos = None
> +        self._open()
> +
> +    def _open(self):
> +        """ (re)open watched file
> +        :return: watcher object
> +        """
> +        try:
> +            self._fhandle = open(self.watch_file, 'r')
> +            self._last_pos = None
> +            self._section_data = []
> +            return True
> +        except IOError:
> +            self._fhandle = None
> +            return False
> +
> +    @staticmethod
> +    def parse_lease(lines):
> +        """ parse dhcp lease
> +        :param lines: lease section as list item
> +        :return: dictionary
> +        """
> +        lease = dict()
> +        lease['address'] = lines[0].split()[1]
> +        for line in lines:
> +            parts =  line.split()
> +            field_name = parts[0]
> +            field_value = None
> +            if field_name in ('starts', 'ends', 'tstp', 'tsfp', 'atsfp',
> 'cltt') and len(parts) >= 3:
> +                dt = '%s %s'%(parts[2], parts[3])
> +                try:
> +                    field_value = time.mktime(datetime.datetime.strptime(dt,
> "%Y/%m/%d %H:%M:%S;").timetuple())
> +                except ValueError:
> +                    field_value = None
> +            elif field_name == 'hardware' and len(parts) >= 3:
> +                field_value = {'hardware-type': parts[1], 'mac-address':
> parts[2]}
> +            elif field_name in('uid', 'client-hostname') and len(parts) >= 2
> and parts[1].find('"') > -1:
> +                field_value = parts[1].split('"')[1]
> +
> +            if field_value is not None:
> +                lease[field_name] = field_value
> +        return lease
> +
> +    def watch(self):
> +        """ watch file, return lease dictionaries
> +        :return: iterator for leases
> +        """
> +        if self._fhandle is None or os.fstat(self._fhandle.fileno()).st_nlink
> == 0:
> +            # nothing to watch, try to (re)open return when failed
> +            if not self._open():
> +                return
> +        elif self._last_pos is not None:
> +            self._fhandle.seek(self._last_pos)
> +
> +        while True:
> +            line = self._fhandle.readline()
> +            if line:
> +                if len(line) > 5 and line[0:5] == 'lease':
> +                    self._section_data.append(line)
> +                elif len(line) > 1 and line[0] == '}':
> +                    self._section_data.append(line)
> +                    yield self.parse_lease(self._section_data)
> +                    self._section_data = []
> +                elif len(self._section_data) > 0:
> +                    self._section_data.append(line)
> +            else:
> +                break
> +
> +        self._last_pos = self._fhandle.tell()
> diff --git a/config/unbound/unbound-dhcpd.py b/config/unbound/unbound-dhcpd.py
> new file mode 100644
> index 0000000..0afedc9
> --- /dev/null
> +++ b/config/unbound/unbound-dhcpd.py
> @@ -0,0 +1,145 @@
> +#!/usr/bin/python2.7
> +
> +"""
> +    Copyright (c) 2016 Ad Schellevis
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions are
> met:
> +
> +    1. Redistributions of source code must retain the above copyright notice,
> +     this list of conditions and the following disclaimer.
> +
> +    2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> WARRANTIES,
> +    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> +    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> THE
> +    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> EXEMPLARY,
> +    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> +    POSSIBILITY OF SUCH DAMAGE.
> +
> +    -------------------------------------------------------------------------
> -------------
> +    watch dhcp lease file and build include file for unbound
> +"""
> +import os
> +import sys
> +
> +sys.path.insert(0, "/usr/lib/python2.7/site-packages")
> +import subprocess
> +import time
> +import tempfile
> +from daemonize import Daemonize
> +import watcherdhcpd
> +import params
> +
> +
> +def unbound_control(commands, output_stream=None):
> +    """ execute (chrooted) unbound-control command
> +        :param commands: command list (parameters)
> +        :param output_stream: (optional)output stream
> +        :return: None
> +    """
> +    output_stream = open(os.devnull, 'w')
> +    subprocess.check_call(['/usr/sbin/chroot', '--userspec=unbound:unbound',
> '/',
> +                           '/usr/sbin/unbound-control', '-c',
> '/etc/unbound/unbound.conf'] + commands,
> +                          stdout=output_stream, stderr=subprocess.STDOUT)
> +    output_stream.seek(0)
> +
> +
> +def unbound_known_addresses():
> +    """ fetch known addresses
> +        :return: list
> +    """
> +    result = list()
> +    with tempfile.NamedTemporaryFile() as output_stream:
> +        unbound_control(['list_local_data'], output_stream)
> +        for line in output_stream.read().split('\n'):
> +            parts = line.split()
> +            if len(parts) > 4 and parts[3] == 'A':
> +                result.append(parts[4])
> +    print result
> +    return result
> +
> +
> +# parse input params
> +app_params = {'pid': '/var/run/unbound_dhcpd.pid',
> +              'domain': 'local',
> +              'target': '/etc/unbound/dhcpleases.conf',
> +              'background': '1'}
> +params.update_params(app_params)
> +
> +
> +def main():
> +    # cleanup interval (seconds)
> +    cleanup_interval = 60
> +
> +    # All times in the lease database are in Coordinated Universal Time
> (UTC), not local time!
> +    tzone = 0
> +    if app_params['background'] <> 1:
> +       print "Add leases for domian:",app_params['domain']
> +
> +    # initiate lease watcher and setup cache
> +    dhcpdleases = watcherdhcpd.DHCPDLease()
> +    cached_leases = dict()
> +    known_addresses = unbound_known_addresses()
> +
> +    # start watching dhcp leases
> +    last_cleanup = time.time()
> +    while True:
> +        dhcpd_changed = False
> +        if time.daylight <> 0:
> +            utctime = time.time() + time.altzone
> +        else:
> +            utctime = time.time() + time.timezone
> +
> +        for lease in dhcpdleases.watch():
> +            if 'ends' in lease and lease['ends'] > utctime and 'client-
> hostname' in lease and 'address' in lease:
> +                cached_leases[lease['address']] = lease
> +                dhcpd_changed = True
> +                if app_params['background'] <> 1:
> +                   print "IP:",lease['address'],"Hostname:",lease['client-
> hostname'],"Start:",lease['starts'],"End:",lease['ends']
> +
> +        if time.time() - last_cleanup > cleanup_interval:
> +            # cleanup every x seconds
> +            last_cleanup = time.time()
> +            addresses = cached_leases.keys()
> +            for address in addresses:
> +                if cached_leases[address]['ends'] < time.time():
> +                    del cached_leases[address]
> +                    dhcpd_changed = True
> +
> +        if dhcpd_changed:
> +            # dump dns output to target
> +            with open(app_params['target'], 'w') as unbound_conf:
> +                for address in cached_leases:
> +                    unbound_conf.write('local-data-ptr: "%s %s.%s"\n' %
> (address,
> +                                                                         cach
> ed_leases[address]['client-hostname'],
> +                                                                         app_
> params['domain']))
> +
> +                    unbound_conf.write('local-data: "%s.%s IN A %s"\n' %
> (cached_leases[address]['client-hostname'],
> +                                                                          app
> _params['domain'],
> +                                                                          add
> ress))
> +            # signal unbound
> +            for address in cached_leases:
> +                if address not in known_addresses:
> +                    fqdn = '%s.%s' % (cached_leases[address]['client-
> hostname'], app_params['domain'])
> +                    unbound_control(['local_data', address, 'PTR', fqdn])
> +                    unbound_control(['local_data', fqdn, 'IN A', address])
> +                    known_addresses.append(address)
> +        # wait for next cycle
> +        time.sleep(5)
> +
> +
> +# startup
> +if app_params['background'] == '1':
> +    daemon = Daemonize(app="unbound_dhcpd", pid=app_params['pid'],
> action=main)
> +    daemon.start()
> +else:
> +    main()
> diff --git a/config/unbound/unbound-switch b/config/unbound/unbound-switch
> new file mode 100755
> index 0000000..60eeb89
> --- /dev/null
> +++ b/config/unbound/unbound-switch
> @@ -0,0 +1,80 @@
> +#!/bin/bash
> +#############################################################################
> ##
> +#                                                                            
>  #
> +# IPFire.org - A linux based
> firewall                                         #
> +# This program is free software: you can redistribute it and/or
> modify        #
> +# it under the terms of the GNU General Public License as published
> by        #
> +# the Free Software Foundation, either version 3 of the License,
> or           #
> +# (at your option) any later
> version.                                         #
> +#                                                                            
>  #
> +# This program is distributed in the hope that it will be
> useful,             #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty
> of              #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> the               #
> +# GNU General Public License for more
> details.                                #
> +#                                                                            
>  #
> +# You should have received a copy of the GNU General Public
> License           #
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.      
>  #
> +#                                                                            
>  #
> +# Description : script to switch the DNS server/proxy in
> IPfire               #
> +#               rerun to easy go back to
> dnsmasq                              #
> +#                                                                            
>  #
> +# Author      : Marcel Lorenz <marcel.lorenz@ipfire.org>                     
>  #
> +#                                                                            
>  #
> +#############################################################################
> ##
> +
> +CGIFILE="/srv/web/ipfire/cgi-bin/services.cgi"
> +
> +install_cron_jobs() {
> +cat > /etc/fcron.weekly/update_unbound_anchor << "EOF"
> +#!/bin/bash
> +# allow max all 30 minutes to update files
> +if [[ $(( (`date +%s` - `stat -L --format %Y /etc/unbound/root.key`) >
> (30*60) )) != 0 ]]; then
> +  wget -q ftp://ftp.internic.net/domain/named.cache -O
> /etc/unbound/root.hints
> +  curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?host
> format=unbound&showintro=0&mimetype=plaintext" > /etc/unbound/blocklists/ad-
> servers.conf
> +  unbound-anchor
> +fi
> +exit 0
> +EOF
> +chmod +x /etc/fcron.weekly/update_unbound_anchor
> +cat > /etc/fcron.hourly/update_unbound_zone << "EOF"
> +#!/bin/bash
> +unbound-zone
> +EOF
> +chmod +x /etc/fcron.hourly/update_unbound_zone
> +}
> +
> +# main switch
> +if [[ -e /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq ]]; then
> +  echo -e "\033[32mActivate Unbound DNS-proxy at start...\033[0m";
> +  # autostart symlinks
> +  rm -f /etc/rc.d/init.d/networking/red.up/05-RS-dnsmasq
> /etc/rc.d/init.d/networking/red.down/05-RS-dnsmasq
> +  mv -f /etc/init.d/network /etc/init.d/network-dnsmasq
> +  mv -f /etc/init.d/network-unbound /etc/init.d/network
> +  # WebIF services.cgi 
> +  sed -i "s|\$Lang::tr{'dns proxy server'} => 'dnsmasq',.*|\$Lang::tr{'dns
> proxy server'} => 'unbound',|" ${CGIFILE}
> +  install_cron_jobs
> +  /etc/fcron.weekly/update_unbound_anchor
> +  # Stop and start services 
> +  /etc/rc.d/init.d/dnsmasq stop
> +  sleep 1
> +  /etc/rc.d/init.d/unbound start
> +
> +else
> +  echo -e "\033[32mActivate dnsmasq DNS-proxy at start...\033[0m";
> +  # autostart symlinks
> +  ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.up/05-RS-
> dnsmasq
> +  ln -sf /etc/rc.d/init.d/dnsmasq /etc/rc.d/init.d/networking/red.down/05-RS-
> dnsmasq
> +  mv -f /etc/init.d/network /etc/init.d/network-unbound
> +  mv -f /etc/init.d/network-dnsmasq /etc/init.d/network
> +  # WebIF services.cgi 
> +  sed -i "s|\$Lang::tr{'dns proxy server'} => 'unbound',.*|\$Lang::tr{'dns
> proxy server'} => 'dnsmasq',|" ${CGIFILE}
> +  # Stop and start services 
> +  /etc/rc.d/init.d/unbound stop
> +  sleep 1
> +  /etc/rc.d/init.d/dnsmasq start
> +  rm -f /etc/fcron.weekly/update_unbound_anchor
> /etc/fcron.hourly/update_unbound_zone;
> +fi
> +unset CGIFILE
> +echo -e "\033[32mdone...\033[0m";
> +exit 0
> +# end of unbound-proxy
> diff --git a/config/unbound/unbound-zone b/config/unbound/unbound-zone
> new file mode 100644
> index 0000000..9a0de1f
> --- /dev/null
> +++ b/config/unbound/unbound-zone
> @@ -0,0 +1,78 @@
> +#!/bin/bash
> +#############################################################################
> ##
> +#                                                                            
>  #
> +# IPFire.org - A linux based
> firewall                                         #
> +# This program is free software: you can redistribute it and/or
> modify        #
> +# it under the terms of the GNU General Public License as published
> by        #
> +# the Free Software Foundation, either version 3 of the License,
> or           #
> +# (at your option) any later
> version.                                         #
> +#                                                                            
>  #
> +# This program is distributed in the hope that it will be
> useful,             #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty
> of              #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> the               #
> +# GNU General Public License for more
> details.                                #
> +#                                                                            
>  #
> +# You should have received a copy of the GNU General Public
> License           #
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.      
>  #
> +#                                                                            
>  #
> +# Description : small script to create the zone file for
> ipfire's             #
> +#               internal domain (for example
> ipfire.local)                    #
> +#                                                                            
>  #
> +# Author      : Marcel Lorenz <marcel.lorenz@ipfire.org>                     
>  #
> +#                                                                            
>  #
> +#############################################################################
> ##
> +
> +ZONEFILE="/etc/unbound/zones/local.conf"
> +HOSTSFILE="/var/ipfire/main/hosts"
> +
> +eval $(/usr/local/bin/readhash /var/ipfire/main/settings)
> +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
> +REV_GREEN=$(echo ${GREEN_ADDRESS} |awk -F. '{print $4"."$3"."$2"."$1}')
> +
> +# overwrite existing file
> +cat > ${ZONEFILE} << "EOF"
> +# This is the automatically created zone file for unbound
> +# please do not edit this file, use the webinterface to add or remove hosts
> +# if need more zones, create a new zone file and restart unbound 
> +#
> +EOF
> +
> +# create zone header 
> +echo "# Zone file created at $(date)" >> ${ZONEFILE}
> +echo "">> ${ZONEFILE} 
> +echo "# zone definition " >> ${ZONEFILE}
> +echo "private-domain: \"${DOMAINNAME}\"" >> ${ZONEFILE}
> +echo "local-zone: \"${DOMAINNAME}.\" static" >> ${ZONEFILE}
> +echo "local-data: \"${HOSTNAME}.${DOMAINNAME}. IN A ${GREEN_ADDRESS}\"" >>
> ${ZONEFILE}
> +echo "local-data: \"wpad.${DOMAINNAME}. IN A ${GREEN_ADDRESS}\"" >>
> ${ZONEFILE}
> +echo "local-data: \"${REV_GREEN}.in-addr.arpa. 10800 IN PTR
> ${HOSTNAME}.${DOMAINNAME}.\"" >> ${ZONEFILE}
> +
> +# write forward entrys to zone file
> +echo "" >> ${ZONEFILE} 
> +echo "# Hosts from /var/ipfire/main/hosts" >> ${ZONEFILE}
> +
> +while read line           
> +do           
> +  if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then
> +    IP=$(echo ${line}|awk -F, '{print $2}')
> +    HOST=$(echo ${line}|awk -F, '{print $3}')
> +    DOMAIN=$(echo ${line}|awk -F, '{print $4}')
> +    echo "local-data: \"${HOST}.${DOMAIN}. IN A ${IP}\"" >> ${ZONEFILE}
> +  fi
> +done < ${HOSTSFILE}
> +
> +# write reverse entrys to zone file
> +echo "" >> ${ZONEFILE} 
> +echo "# reverse entrys" >> ${ZONEFILE}
> +while read line           
> +do           
> +  if [[ $(echo ${line}|awk -F, '{print $1}') = on ]]; then
> +    IP=$(echo ${line}|awk -F, '{print $2}'|awk -F. '{print
> $4"."$3"."$2"."$1}')
> +    HOST=$(echo ${line}|awk -F, '{print $3}')
> +    DOMAIN=$(echo ${line}|awk -F, '{print $4}')
> +    echo "local-data: \"${IP}.in-addr.arpa. 10800 IN PTR ${HOST}.${DOMAIN}\""
> >> ${ZONEFILE}
> +  fi
> +done < ${HOSTSFILE}
> +unset IP HOST DOMAIN REV_GREEN;
> +exit 0
> +# end of unbound-zone
> diff --git a/config/unbound/unbound.conf b/config/unbound/unbound.conf
> new file mode 100644
> index 0000000..8dc72e6
> --- /dev/null
> +++ b/config/unbound/unbound.conf
> @@ -0,0 +1,123 @@
> +#
> +# Unbound configuration file for IPFire
> +#
> +# The full documentation is available at:
> +# https://www.unbound.net/documentation/unbound.conf.html
> +#
> +
> +server:
> +	# common server options
> +	chroot: "/etc/unbound"
> +	username: "unbound"
> +	pidfile: "/var/run/unbound.pid"
> +	num-threads: 2
> +	port: 53
> +	do-ip4: yes
> +	do-ip6: no
> +	do-udp: yes
> +	do-tcp: yes
> +	prefetch: yes
> +	so-reuseport: yes
> +	cache-min-ttl: 3600
> +	cache-max-ttl: 86400
> +	unwanted-reply-threshold: 10000
> +	do-not-query-localhost: yes
> +
> +	# logging options
> +	logfile: "log/unbound.log"
> +	use-syslog: no
> +	verbosity: 1
> +	log-queries: no
> +	log-time-ascii: yes
> +
> +	# Unbound Statistics
> +	statistics-interval: 3600
> +	statistics-cumulative: yes
> +	extended-statistics: yes
> +
> +	# privacy options
> +	hide-identity: yes
> +	hide-version: yes
> +	qname-minimisation: yes
> +	minimal-responses: yes
> +
> +	# hardening options (some experimental)
> +	harden-glue: yes
> +	harden-large-queries: yes
> +	harden-dnssec-stripped: yes
> +	harden-short-bufsize: no
> +	harden-below-nxdomain: no
> +	harden-referral-path: no
> +	harden-algo-downgrade: no
> +	use-caps-for-id: yes
> +
> +	# listen on localhost interface
> +	interface: 127.0.0.1
> +
> +	# file with ipfire interfaces
> +	include:  "/etc/unbound/interfaces.conf"
> +
> +	# control which clients are allowed to make (recursive) queries
> +	access-control: 0.0.0.0/0 refuse
> +	access-control: 127.0.0.0/8 allow
> +	access-control: ::0/0 refuse
> +	access-control: ::1 allow
> +	access-control: ::ffff:127.0.0.1 allow
> +
> +	# file with ipfire networks
> +	include: "/etc/unbound/access.conf"
> +
> +	# dnssec main options
> +	val-clean-additional: yes
> +	val-log-level: 1
> +	# file with ipfire dnssec configuration
> +	include:  "/etc/unbound/dnssec.conf"
> +
> +	# DNS Rebinding
> +	# For DNS Rebinding prevention
> +	#
> +	# All these addresses are either private or should not be routable in
> the global IPv4 or IPv6 internet.
> +	# IPv4 Addresses
> +	private-address: 0.0.0.0/8       # Broadcast address
> +	private-address: 10.0.0.0/8
> +	private-address: 127.0.0.0/8     # Loopback Localhost
> +	private-address: 172.16.0.0/12
> +	private-address: 192.168.0.0/16
> +	private-address: 169.254.0.0/16
> +	private-address: 198.18.0.0/15   # Used for testing inter-network
> communications
> +	private-address: 198.51.100.0/24 # Documentation network TEST-NET-2
> +	private-address: 203.0.113.0/24  # Documentation network TEST-NET-3
> +	private-address: 233.252.0.0/24  # Documentation network MCAST-TEST-
> NET
> +	# IPv6 Addresses
> +	private-address: ::1/128         # Loopback Localhost
> +	private-address: 2001:db8::/32   # Documentation network IPv6
> +	private-address: fc00::/8        # Unique local address (ULA) part of
> "fc00::/7", not defined yet
> +	private-address: fd00::/8        # Unique local address (ULA) part of
> "fc00::/7", "/48" prefix group
> +	private-address: fe80::/10       # Link-local address (LLA)
> +
> +	# file with root servers 
> +	root-hints: "/etc/unbound/root.hints"
> +
> +	# custom DNS zone files
> +	include: "/etc/unbound/zones/*.conf"
> +
> +	# DHCP leases (if configured)
> +	include: /etc/unbound/dhcpleases.conf
> +
> +	# Blocklists
> +	include: "/etc/unbound/blocklists/*.conf"
> +# end server config
> +
> +# enable remote control only on localhost
> +remote-control:
> +	control-enable: yes
> +	control-use-cert: yes
> +	control-interface: 127.0.0.1
> +	server-key-file: "/etc/unbound/unbound_server.key"
> +	server-cert-file: "/etc/unbound/unbound_server.pem"
> +	control-key-file: "/etc/unbound/unbound_control.key"
> +	control-cert-file: "/etc/unbound/unbound_control.pem"
> +# end remote control config
> +
> +# custom DNS forward config
> +include: "/etc/unbound/forward.conf"
> diff --git a/lfs/unbound b/lfs/unbound
> new file mode 100644
> index 0000000..d91c0f9
> --- /dev/null
> +++ b/lfs/unbound
> @@ -0,0 +1,103 @@
> +#############################################################################
> ##
> +#                                                                            
>  #
> +# IPFire.org - A linux based
> firewall                                         #
> +# Copyright (C) 2007  Michael Tremer & Christian
> Schmidt                      #
> +#                                                                            
>  #
> +# This program is free software: you can redistribute it and/or
> modify        #
> +# it under the terms of the GNU General Public License as published
> by        #
> +# the Free Software Foundation, either version 3 of the License,
> or           #
> +# (at your option) any later
> version.                                         #
> +#                                                                            
>  #
> +# This program is distributed in the hope that it will be
> useful,             #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty
> of              #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> the               #
> +# GNU General Public License for more
> details.                                #
> +#                                                                            
>  #
> +# You should have received a copy of the GNU General Public
> License           #
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.      
>  #
> +#                                                                            
>  #
> +#############################################################################
> ##
> +
> +#############################################################################
> ##
> +# Definitions
> +#############################################################################
> ##
> +
> +include Config
> +
> +VER        = 1.5.9
> +THISAPP    = unbound-$(VER)
> +DL_FILE    = $(THISAPP).tar.gz
> +DL_FROM    = $(URL_IPFIRE)
> +DIR_APP    = $(DIR_SRC)/$(THISAPP)
> +TARGET     = $(DIR_INFO)/$(THISAPP)
> +PROG       = unbound
> +PAK_VER    = 1
> +DEPS       = ""
> +
> +#############################################################################
> ##
> +# Top-level Rules
> +#############################################################################
> ##
> +
> +objects = $(DL_FILE)
> +
> +$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
> +
> +$(DL_FILE)_MD5 = 0cefa62c1690b4db18583db84bff00e3
> +
> +install : $(TARGET)
> +
> +check : $(patsubst %,$(DIR_CHK)/%,$(objects))
> +
> +download :$(patsubst %,$(DIR_DL)/%,$(objects))
> +
> +md5 : $(subst %,%_MD5,$(objects))
> +
> +dist: 
> +	$(PAK)
> +
> +#############################################################################
> ##
> +# Downloading, checking, md5sum
> +#############################################################################
> ##
> +
> +$(patsubst %,$(DIR_CHK)/%,$(objects)) :
> +	@$(CHECK)
> +
> +$(patsubst %,$(DIR_DL)/%,$(objects)) :
> +	@$(LOAD)
> +
> +$(subst %,%_MD5,$(objects)) :
> +	@$(MD5)
> +
> +#############################################################################
> ##
> +# Installation Details
> +#############################################################################
> ##
> +
> +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
> +	@$(PREBUILD)
> +	@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
> +	cd $(DIR_APP) && ./configure \
> +			--prefix=/usr \
> +			--sysconfdir=/etc \
> +			--disable-static \
> +			--with-libevent \
> +			--with-pyunbound \
> +			--with-pidfile=/var/run/unbound.pid
> +	cd $(DIR_APP) && make $(MAKETUNING)
> +	cd $(DIR_APP) && make install
> +	mv -v /usr/sbin/unbound-host /usr/bin/
> +	# add ipfire config
> +	mkdir -pv /etc/unbound/blocklists
> +	mv -v /etc/unbound/unbound.conf /etc/unbound/unbound_org.conf
> +	install -v -m 644 $(DIR_SRC)/config/unbound/*.conf /etc/unbound/
> +	install -v -m 644 $(DIR_SRC)/config/unbound/root.hints /etc/unbound/
> +	install -v -m 644 $(DIR_SRC)/config/unbound/root.key /etc/unbound/
> +	install -v -m 644 $(DIR_SRC)/config/unbound/blocklists/*.conf
> /etc/unbound/blocklists/
> +	install -v -m 644 $(DIR_SRC)/config/unbound/site-packages/*
> /usr/lib/python2.7/site-packages/
> +	install -v -m 754 $(DIR_SRC)/config/unbound/unbound-switch /usr/sbin/
> +	install -v -m 754 $(DIR_SRC)/config/unbound/unbound-zone /usr/sbin/
> +	install -v -m 754 $(DIR_SRC)/config/unbound/unbound-dhcpd.py
> /usr/sbin/
> +	install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound
> /etc/rc.d/init.d/
> +	install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/unbound-dhcpd
> /etc/rc.d/init.d/
> +	install -v -m 754 $(DIR_SRC)/src/initscripts/init.d/network-unbound
> /etc/rc.d/init.d/
> +	@rm -rf $(DIR_APP)
> +	@$(POSTBUILD)
> diff --git a/make.sh b/make.sh
> index a9fac52..74bc06a 100755
> --- a/make.sh
> +++ b/make.sh
> @@ -870,6 +870,7 @@ buildipfire() {
>    ipfiremake libpciaccess
>    ipfiremake libyajl
>    ipfiremake libvirt
> +  ipfiremake unbound
>  }
>  
>  buildinstaller() {
> diff --git a/src/initscripts/init.d/network-unbound
> b/src/initscripts/init.d/network-unbound
> new file mode 100644
> index 0000000..31fe173
> --- /dev/null
> +++ b/src/initscripts/init.d/network-unbound
> @@ -0,0 +1,114 @@
> +#!/bin/sh
> +########################################################################
> +# Begin $rc_base/init.d/network
> +#
> +# Description : Network Control Script
> +#
> +# Authors     : Michael Tremer - mitch@ipfire.org
> +#
> +# Version     : 01.00
> +#
> +# Notes       : Written for IPFire by its team
> +#
> +########################################################################
> +
> +. /etc/sysconfig/rc
> +. ${rc_functions}
> +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
> +
> +
> +DO="${1}"
> +shift
> +
> +if [ -n "${1}" ]; then
> +	ALL=0
> +	for i in green red blue orange; do
> +		eval "${i}=0"
> +	done
> +else
> +	ALL=1
> +	for i in green red blue orange; do
> +		eval "${i}=1"
> +	done
> +fi
> +
> +while [ ! $# = 0 ]; do
> +	for i in green red blue orange; do
> +		if [ "${i}" == "${1}" ]; then
> +			eval "${i}=1"
> +			shift
> +		fi
> +	done
> +done
> +
> +case "${DO}" in
> +	start)
> +
> +		# Starting interfaces...
> +		# GREEN
> +		[ "$green" == "1" ] && /etc/rc.d/init.d/networking/green
> start
> +
> +		# BLUE
> +		[ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o
> "$CONFIG_TYPE" = "4" ] && \
> +			/etc/rc.d/init.d/networking/blue start
> +
> +		# ORANGE
> +		[ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o
> "$CONFIG_TYPE" = "4" ] && \
> +			/etc/rc.d/init.d/networking/orange start
> +
> +		# RED
> +		if [ "$red" == "1" ]; then
> +			if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o
> "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then
> +				# Remove possible leftover files
> +				rm -f /var/ipfire/red/{active,device,dial-on-
> demand,dns1,dns2,local-ipaddress,remote-ipaddress,resolv.conf}
> +				[ "$AUTOCONNECT" == "off" ] ||
> /etc/rc.d/init.d/networking/red start
> +			fi
> +		fi
> +
> +		/etc/rc.d/init.d/static-routes start
> +		[ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound start
> +		;;
> +
> +	stop)
> +
> +		[ "${ALL}" == "1" ] && /etc/rc.d/init.d/unbound stop
> +		# Stopping interfaces...
> +		# GREEN
> +		[ "$green" == "1" ] && /etc/rc.d/init.d/networking/green stop
> +	
> +		# BLUE
> +		[ "$blue" == "1" ] && [ "$CONFIG_TYPE" = "3" -o
> "$CONFIG_TYPE" = "4" ] && \
> +			/etc/rc.d/init.d/networking/blue stop
> +
> +		# ORANGE
> +		[ "$orange" == "1" ] && [ "$CONFIG_TYPE" = "2" -o
> "$CONFIG_TYPE" = "4" ] && \
> +			/etc/rc.d/init.d/networking/orange stop
> +
> +		# RED
> +		if [ "$red" == "1" ]; then
> +			if [ "$CONFIG_TYPE" = "1" -o "$CONFIG_TYPE" = "2" -o
> "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then
> +				/etc/rc.d/init.d/networking/red stop
> +			fi
> +		fi
> +
> +		exit 0
> +		;;
> +
> +	restart)
> +		for i in green red blue orange; do
> +			if [ "${!i}" == "1" ]; then
> +				ARGS+=" ${i}"
> +			fi
> +		done
> +		${0} stop ${ARGS}
> +		sleep 1
> +		${0} start ${ARGS}
> +		;;
> +
> +	*)
> +		echo "Usage: ${0} {start|stop|restart} [device(s)]"
> +		exit 1
> +		;;
> +esac
> +
> +# End /etc/rc.d/init.d/network
> diff --git a/src/initscripts/init.d/unbound b/src/initscripts/init.d/unbound
> new file mode 100644
> index 0000000..8e6881e
> --- /dev/null
> +++ b/src/initscripts/init.d/unbound
> @@ -0,0 +1,178 @@
> +#!/bin/sh
> +# Begin $rc_base/init.d/unbound
> +
> +# Description : Unbound DNS resolver boot script for IPfire
> +# Author      : Marcel Lorenz <marcel.lorenz@ipfire.org>
> +#
> +# Comment     : This init script additional starts the dhcpd watcher daemon
> +#               if DNS-Update (RFC2136) in web interface enabled
> +
> +. /etc/sysconfig/rc
> +. ${rc_functions}
> +
> +if [[ ! -d /run/var ]]; then mkdir /run/var; fi;
> +
> +CONTROL_INTERFACE_FILE=1
> +CONTROL_ACCESS_FILE=1
> +USE_CUSTOM_FORWARDS=0
> +ENABLE_DNSSEC=1
> +
> +# Unbound daemon pid file
> +PIDFILE=/var/run/unbound.pid
> +
> +# Watcher deamon pid file must be the same in unbound main init script
> +WAPIDFILE=/var/run/unbound_dhcpd.pid
> +
> +function cidr() {
> +    local cidr nbits IFS;
> +    IFS=. read -r i1 i2 i3 i4 <<< ${1}
> +    IFS=. read -r m1 m2 m3 m4 <<< ${2}
> +    cidr=$(printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 &
> m3))" "$((i4 & m4))")
> +    nbits=0
> +    IFS=.
> +    for dec in $2 ; do
> +        case $dec in
> +            255) let nbits+=8;;
> +            254) let nbits+=7;;
> +            252) let nbits+=6;;
> +            248) let nbits+=5;;
> +            240) let nbits+=4;;
> +            224) let nbits+=3;;
> +            192) let nbits+=2;;
> +            128) let nbits+=1;;
> +            0);;
> +            *) echo "Error: $dec is not recognised"; exit 1
> +        esac
> +    done
> +    echo "${cidr}/${nbits}"
> +}
> +
> +case "$1" in
> +	start)
> +
> +	  if [[ -f ${PIDFILE} ]]; then
> +	    log_warning_msg "Unbound daemon is running with Process ID $(cat
> ${PIDFILE})"
> +	  else
> +	    eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
> +	    #ARGS="$CUSTOM_ARGS"
> +	    #[ "$DOMAIN_NAME_GREEN" != "" ] && ARGS="$ARGS -s
> $DOMAIN_NAME_GREEN"
> +
> +	    echo > /var/ipfire/red/resolv.conf # Clear it
> +	    if [ -e "/var/ipfire/red/dns1" ]; then
> +	       DNS1=$(cat /var/ipfire/red/dns1 2>/dev/null)
> +	      if [ ! -z ${DNS1} ]; then
> +		echo "nameserver ${DNS1}" >> /var/ipfire/red/resolv.conf
> +		NAMESERVERS="${DNS1} "
> +	      fi
> +	    fi
> +	    if [ -e "/var/ipfire/red/dns2" ]; then
> +	      DNS2=$(cat /var/ipfire/red/dns2 2>/dev/null)
> +	      if [ ! -z ${DNS2} ]; then
> +		echo "nameserver ${DNS2}" >> /var/ipfire/red/resolv.conf
> +		NAMESERVERS+="${DNS2} "
> +	      fi
> +	    fi
> +
> +	    # create unbound interfaces.conf
> +	    if [ ${CONTROL_INTERFACE_FILE} = 1 ]; then
> +		  echo -n > /etc/unbound/interfaces.conf # Clear it
> +	      if [ ! -z ${GREEN_ADDRESS} ]; then
> +		echo "interface: ${GREEN_ADDRESS}" >>
> /etc/unbound/interfaces.conf
> +	      fi
> +	      if [ ! -z ${BLUE_ADDRESS} ]; then
> +		echo "interface: ${BLUE_ADDRESS}" >>
> /etc/unbound/interfaces.conf
> +	      fi
> +		if [ ! -z ${ORANGE_ADDRESS} ]; then
> +		echo "interface: ${ORANGE_ADDRESS}" >>
> /etc/unbound/interfaces.conf
> +	      fi
> +	    fi
> +
> +	    # create unbound access.conf
> +	    if [ ${CONTROL_ACCESS_FILE} = 1 ]; then
> +	      echo -n > /etc/unbound/access.conf # Clear it
> +	      if [ ! -z ${GREEN_ADDRESS} ]; then
> +		echo "access-control: $(cidr ${GREEN_ADDRESS}
> ${GREEN_NETMASK}) allow" >> /etc/unbound/access.conf
> +	      fi
> +	      if [ ! -z ${BLUE_ADDRESS} ]; then
> +		echo "access-control: $(cidr ${BLUE_ADDRESS} ${BLUE_NETMASK})
> allow" >> /etc/unbound/access.conf
> +	      fi
> +	      if [ ! -z ${ORANGE_ADDRESS} ]; then
> +		echo "access-control: $(cidr ${ORANGE_ADDRESS}
> ${ORANGE_NETMASK}) allow" >> /etc/unbound/access.conf
> +	      fi
> +	    fi
> +
> +	    # create unbound dnssec.conf
> +	    echo -n > /etc/unbound/dnssec.conf # Clear it
> +	    if [ ${ENABLE_DNSSEC} = 1 ]; then
> +	      echo "	# dessec enabled per default" >>
> /etc/unbound/dnssec.conf
> +	      echo "	# no necessary config options in this file" >>
> /etc/unbound/dnssec.conf
> +	    else
> +	      echo "	# dnssec now disabled" >>
> /etc/unbound/dnssec.conf
> +	      echo "	module-config: iterator" >>
> /etc/unbound/dnssec.conf
> +	      echo "	val-permissive-mode: yes" >>
> /etc/unbound/dnssec.conf
> +	    fi
> +
> +	    # create zone file for internal ipfire domain 
> +	    unbound-zone
> +
> +	    boot_mesg "Starting Unbound DNS proxy..."
> +	    unbound-anchor
> +	    loadproc /usr/sbin/unbound
> +
> +	    # start dhcpd watcher daemon if DNS-Update (RFC2136) activated
> +	    eval $(/usr/local/bin/readhash /var/ipfire/dhcp/settings)
> +	    if [[ ${DNS_UPDATE_ENABLED} = on && ! -f ${WAPIDFILE} ]]; then
> +	      /etc/rc.d/init.d/unbound-dhcpd start
> +	    fi
> +
> +	    # use setup configured DNS servers 
> +	    if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then
> +	       unbound-control forward_add +i . ${NAMESERVERS} &> /dev/null
> +	    fi;
> +
> +	    FORWADRS=$(unbound-control list_forwards |sed 's|. IN forward
> ||g'|sed 's|+i ||g')
> +	    if [ "${USE_CUSTOM_FORWARDS}" -eq 0 ]; then
> +	      boot_mesg "Using DNS server(s): ${FORWADRS}"
> +	    else
> +	      boot_mesg "Using custom DNS server(s): ${FORWADRS}"
> +	    fi
> +	    if [ ${ENABLE_DNSSEC} = 1 ]; then
> +	      boot_mesg "DNSSEC is enabled!"
> +	    else
> +	      boot_mesg "DNSSEC is disabled!"
> +	    fi
> +	  fi 
> +	  ;;
> +
> +	stop)
> +
> +	  if [[ -f ${PIDFILE} ]]; then
> +	    # stop dhcpd watcher daemon if activted
> +	    if [[ -f ${WAPIDFILE} ]]; then
> +	      /etc/rc.d/init.d/unbound-dhcpd stop
> +	    fi
> +	    # stop Unbound daemon
> +	    boot_mesg "Stopping Unbound DNS proxy..."
> +	    killproc -p "/var/run/unbound.pid" /usr/sbin/unbound
> +	  else
> +	    log_warning_msg "Unbound daemon is not running..."
> +	  fi
> +	  ;;
> +
> +	restart)
> +	  $0 stop
> +	  sleep 1
> +	  $0 start
> +	  ;;
> +
> +	status)
> +	  statusproc /usr/sbin/unbound
> +	  ;;
> +
> +	*)
> +	  echo "Usage: $0 {start|stop|restart|status}"
> +	  exit 1
> +	  ;;
> +esac
> +
> +# End $rc_base/init.d/unbound
> diff --git a/src/initscripts/init.d/unbound-dhcpd
> b/src/initscripts/init.d/unbound-dhcpd
> new file mode 100644
> index 0000000..4c24a3c
> --- /dev/null
> +++ b/src/initscripts/init.d/unbound-dhcpd
> @@ -0,0 +1,61 @@
> +#!/bin/sh
> +# Begin $rc_base/init.d/unbound-dhcpd
> +
> +# Description : Unbound dhcpd lease file wachter daemon boot script for
> IPFire
> +# Author      : Marcel Lorenz <marcel.lorenz@ipfire.org>
> +
> +. /etc/sysconfig/rc
> +. $rc_functions
> +
> +PIDFILE=/var/run/unbound_dhcpd.pid
> +SETFILE=/var/ipfire/main/settings
> +
> +case "$1" in
> +	start)
> +		if [[ -f ${PIDFILE} ]]; then
> +		  log_warning_msg "Unbound dhcpd watcher daemon is running
> with Process ID $(cat ${PIDFILE})"
> +		else
> +		  eval $(/usr/local/bin/readhash ${SETFILE})
> +		  boot_mesg "Starting Unbound dhcpd watcher deamon..."
> +		  loadproc /usr/bin/python /usr/sbin/unbound-dhcpd.py /domain
> ${DOMAINNAME} /pid ${PIDFILE}
> +		fi
> +		;;
> +
> +	stop)
> +		if [[ -f ${PIDFILE} ]]; then
> +		  boot_mesg "Stopping Unbound dhcpd watcher deamon..."
> +		  kill $(/bin/cat ${PIDFILE})
> +		  sleep 1
> +		  if [[ -f ${PIDFILE} ]]; then
> +		    echo_failure
> +		  else
> +		    echo_ok
> +		  fi
> +		else
> +		  log_warning_msg "Unbound dhcpd watcher daemon is not
> running..."
> +		fi
> +		;;
> +
> +	restart)
> +		$0 stop
> +		sleep 1
> +		$0 start
> +		;;
> +
> +	status)
> +		if [[ -f "$PIDFILE" ]]; then 
> +		  echo -e "\\033[1;36mUnbound dhcpd watcher daemon is running
> with Process ID $(cat ${PIDFILE})\\033[0;39m"
> +		  exit 0
> +		else
> +		  echo -e "\\033[1;36mUnbound dhcpd watcher daemon is not
> running...\\033[0;39m"
> +		  exit 0
> +		fi
> +		;;
> +
> +	*)
> +		echo "Usage: $0 {start|stop|restart|status}"
> +		exit 1
> +		;;
> +esac
> +
> +# End $rc_base/init.d/unbound-dhcpd
> \ No newline at end of file
> diff --git a/src/paks/unbound/install.sh b/src/paks/unbound/install.sh
> new file mode 100644
> index 0000000..84c93f3
> --- /dev/null
> +++ b/src/paks/unbound/install.sh
> @@ -0,0 +1,70 @@
> +#!/bin/bash
> +############################################################################
> +#                                                                          #
> +# This file is part of the IPFire Firewall.                                #
> +#                                                                          #
> +# IPFire is free software; you can redistribute it and/or modify           #
> +# it under the terms of the GNU General Public License as published by     #
> +# the Free Software Foundation; either version 2 of the License, or        #
> +# (at your option) any later version.                                      #
> +#                                                                          #
> +# IPFire is distributed in the hope that it will be useful,                #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of           #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
> +# GNU General Public License for more details.                             #
> +#                                                                          #
> +# You should have received a copy of the GNU General Public License        #
> +# along with IPFire; if not, write to the Free Software                    #
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA #
> +#                                                                          #
> +# Copyright (C) 2016 IPFire-Team <info@ipfire.org>.                        #
> +#                                                                          #
> +############################################################################
> +#
> +. /opt/pakfire/lib/functions.sh
> +extract_files
> +restore_backup ${NAME}
> +
> +# add unbound user and group
> +groupadd -g 85 unbound 
> +useradd -c "Unbound DNS resolver" -d /var/lib/unbound -u 85 -g unbound -s
> /bin/false unbound
> +
> +# create config subdir's
> +mkdir -pv /etc/unbound/log /etc/unbound/zones  /var/log/unbound
> +chown unbound:unbound -R /var/log/unbound/ /etc/unbound/log/;
> +
> +echo "Add logrotate config for unbound now..."
> +LOGROTATE=$(grep -A 1 '/var/log/unbound/unbound.log' /etc/logrotate.conf)
> +if [[ ! "${LOGROTATE}" ]]; then
> +cat >> /etc/logrotate.conf << "EOF"
> +# Unbound
> +/var/log/unbound/unbound.log {
> +    daily
> +    rotate 30
> +    copytruncate
> +    compress
> +    missingok
> +    prerotate
> +      /bin/mv -f /etc/unbound/log/unbound.log /var/log/unbound/unbound.log
> +      /usr/sbin/unbound-control log_reopen &> /dev/null
> +    endscript
> +}
> +
> +EOF
> +touch /etc/unbound/dhcpleases.conf
> +touch /var/log/unbound/unbound.log
> +chown unbound:unbound /var/log/unbound/unbound.log
> +fi
> +
> +# create link to current logfile
> +ln -svf /etc/unbound/log/unbound.log /var/log/unbound/current.log
> +
> +# create remote control key files and set rights 
> +/usr/sbin/unbound-control-setup &> /dev/null
> +chown unbound:unbound
> /etc/unbound/{unbound_control.*,unbound_server.*,root.key,root.hints}
> +
> +# at last switch the DNS-Resolver to unbound
> +/usr/sbin/unbound-switch
> +
> +unset LOGROTATE
> +exit 0
> diff --git a/src/paks/unbound/uninstall.sh b/src/paks/unbound/uninstall.sh
> new file mode 100644
> index 0000000..fc39f9f
> --- /dev/null
> +++ b/src/paks/unbound/uninstall.sh
> @@ -0,0 +1,27 @@
> +#!/bin/bash
> +############################################################################
> +#                                                                          #
> +# This file is part of the IPFire Firewall.                                #
> +#                                                                          #
> +# IPFire is free software; you can redistribute it and/or modify           #
> +# it under the terms of the GNU General Public License as published by     #
> +# the Free Software Foundation; either version 2 of the License, or        #
> +# (at your option) any later version.                                      #
> +#                                                                          #
> +# IPFire is distributed in the hope that it will be useful,                #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of           #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
> +# GNU General Public License for more details.                             #
> +#                                                                          #
> +# You should have received a copy of the GNU General Public License        #
> +# along with IPFire; if not, write to the Free Software                    #
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA #
> +#                                                                          #
> +# Copyright (C) 2007 IPFire-Team <info@ipfire.org>.                        #
> +#                                                                          #
> +############################################################################
> +#
> +. /opt/pakfire/lib/functions.sh
> +/usr/sbin/resolver.sh
> +make_backup ${NAME}
> +remove_files
> diff --git a/src/paks/unbound/update.sh b/src/paks/unbound/update.sh
> new file mode 100644
> index 0000000..89c40d0
> --- /dev/null
> +++ b/src/paks/unbound/update.sh
> @@ -0,0 +1,26 @@
> +#!/bin/bash
> +############################################################################
> +#                                                                          #
> +# This file is part of the IPFire Firewall.                                #
> +#                                                                          #
> +# IPFire is free software; you can redistribute it and/or modify           #
> +# it under the terms of the GNU General Public License as published by     #
> +# the Free Software Foundation; either version 2 of the License, or        #
> +# (at your option) any later version.                                      #
> +#                                                                          #
> +# IPFire is distributed in the hope that it will be useful,                #
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of           #
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
> +# GNU General Public License for more details.                             #
> +#                                                                          #
> +# You should have received a copy of the GNU General Public License        #
> +# along with IPFire; if not, write to the Free Software                    #
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA #
> +#                                                                          #
> +# Copyright (C) 2007 IPFire-Team <info@ipfire.org>.                        #
> +#                                                                          #
> +############################################################################
> +#
> +. /opt/pakfire/lib/functions.sh
> +./uninstall.sh
> +./install.sh