summaryrefslogtreecommitdiff
path: root/net-dns/rbldnsd
diff options
context:
space:
mode:
Diffstat (limited to 'net-dns/rbldnsd')
-rw-r--r--net-dns/rbldnsd/Manifest11
-rw-r--r--net-dns/rbldnsd/files/confd-0.997a35
-rw-r--r--net-dns/rbldnsd/files/initd-0.997a24
-rw-r--r--net-dns/rbldnsd/files/rbldnsd-0.997a-format-security-compile-fix.patch30
-rw-r--r--net-dns/rbldnsd/files/rbldnsd-0.997a-robust-ipv6-test-support.patch329
-rw-r--r--net-dns/rbldnsd/files/rbldnsd-0.998-fix-huge-zone-OOM.patch60
-rw-r--r--net-dns/rbldnsd/metadata.xml30
-rw-r--r--net-dns/rbldnsd/rbldnsd-0.998-r2.ebuild67
-rw-r--r--net-dns/rbldnsd/rbldnsd-0.998.ebuild66
9 files changed, 652 insertions, 0 deletions
diff --git a/net-dns/rbldnsd/Manifest b/net-dns/rbldnsd/Manifest
new file mode 100644
index 000000000000..769c115d8230
--- /dev/null
+++ b/net-dns/rbldnsd/Manifest
@@ -0,0 +1,11 @@
+AUX confd-0.997a 1375 SHA256 10930e7738de72c588182b84a4db5c574948ccc870308de175d2e9b3edd52db9 SHA512 c26f561a0906704c8eb32d8748428b120489cb02d0c9b5ea814b7b4eb71e2ccdddc153d442ebcc46789e65c8c3aa3a305bbf56e6030f3b9994c6d7d247120669 WHIRLPOOL cff5b0a6cf15baa12c49e9d43674302511900afe502dff5a197a8048eddd3812892e4a8633665b854152bb5b00a9d276fca7463d2356bafd884b837dfb8a2075
+AUX initd-0.997a 546 SHA256 261449b46c659b3e8fafad2572cec7ee42b5a36a9600820bf06cd7a697ac2a2d SHA512 2d18c5126ee1cf79e45881cf358f9d9299387dc1b2c0ee2433f85f617694ba11fb2c80703c18002995dc3d1f3d9d561b9b473a9c705b5b0c8ff282385b2e3170 WHIRLPOOL aa79aa99e1db25835ea88089005d7bbab1b62c748cb37f2c01c16dd68d9d2b5726764905d83ce27e0a5466c5c90b86bf1addd2c7fef9d00735d3a6c6db3cab94
+AUX rbldnsd-0.997a-format-security-compile-fix.patch 914 SHA256 13d806d81dcae2038e1b8542fc0ed19cdd8b42d6be48ab11ff181a1d9cd551d4 SHA512 fe61d08ca56759cbce9e078576b3efd4e0bfa35108ca3921d9aa02d78d8e5fc8bae4ea4c38cc9695379ea28f058facf70978c8aa5ecc7d53742222a28dcbc166 WHIRLPOOL 8e8c8092725adab1a2b7663e04719b876bded4ca7d0c2b9c8e7d2cf1c550a63f2fffa872230ff545a472df190ae9fe1f8e3ca6728f329c30eaaa679e7cbd95a4
+AUX rbldnsd-0.997a-robust-ipv6-test-support.patch 10867 SHA256 92c21510d898b0f8e48ee9b53fd59dcd1386b6c446ba92859d7189a78f989420 SHA512 a502df0c102a92dbccba482741ef628cde409f6d87d8467b66a0e4f595f8b28b9e99db0832ca27e3dbf317018b33f666b8bb8962988177cfaf1e0d28b6bf21d6 WHIRLPOOL e703fd7a7e471a67e9e43156257bbc421eb6728f6d60f25774397eae60030f143d0265a1f8f85c6f5913deced5fa274111662d865bff11dfc1bae635054b555a
+AUX rbldnsd-0.998-fix-huge-zone-OOM.patch 1659 SHA256 d99bb2117552ca8a60a65854122a4864b8e4bab7f17d633372ea0f67a68b9303 SHA512 2342d29322e6a5b726319a60c54a7f8d19b020e3dfc8a9d236ac7b6a55d9755b9afe1505c2f835604016fb899630074090baa737b2d3a24f7b4d4e4d911b0443 WHIRLPOOL 6d69d9f51a4eb7ae8907995b40da138995637a40aa6d96e793b2269ee2a56c52f396df4f604d4add59964a6eda3aef2aab51657a6ed291aa3cc5de006ea10263
+DIST rbldnsd-0.998.tar.gz 145363 SHA256 bc36082d46828ecdc0c9e3f8f009596746e1242b2b4002ab9cf9b93fe36e4924 SHA512 7b6fb106f8188b2ce6e05b622cf90a393a4642f00faa5bddc184ce02dbd2beee9d8de22cb09ae53a25c475f28f99d13fbf6252f0d4c1d72bf47ba23f769e7074 WHIRLPOOL 27165b85c85de5cd4db65979a093104d2f614af8163f10d65b5ac28eb443d4b9584ac5501314b8c3a8df3d730a0658f8cf88b0d6eb35efb9f3a17f25fc0ed49a
+EBUILD rbldnsd-0.998-r2.ebuild 1568 SHA256 d6ea19d5b81951dc132a40a2049abd5523c0e1f9915bc4c43ab342ca6825167d SHA512 4d027da14375e3d51a9fa8d9bc10697996c5ff5a68ba75d322c02b7ee8ddce062f993cec3ca2070fbd6d8f2d8452c99529e7d5b7e9a771b34dde110c43298b76 WHIRLPOOL 9702b468b489a9c28b2ae0ed3326ebeb6bb853cf3001e0849bf17e77d8b8f6fb8c5163b8da1babfc1eb7e1e781c2283e7124f6f5e507b3988d6590e1df9ac7de
+EBUILD rbldnsd-0.998.ebuild 1550 SHA256 25833302a1be2613b06195ffec8cdb25c65131b429eef37fd1594493b88ab5df SHA512 0035d4f3a4119a03cb7f102ae63a25ef09d85e216dae8fd847a050b670ac281b624fa4873fe6d4cc0454c4e67d891748509a4f0f2180bdb932def5ccc7aa999a WHIRLPOOL 788f38ab5a02fdf0e0a0d547a94455fb7ea787b7cde465c7832a1e0ab7765426af25ba10752b890d5a347a91010e04bbc7a49183b62afa2e6b46411caf190e4e
+MISC ChangeLog 4565 SHA256 446438d603a79732de9cda4fe955bedaa948b11285210ec6c12d860f6e04a6b1 SHA512 102b574f07561e982dc37b82e789ffea2a24620627db1b1c907de45a0237b9b4cac43633b788ae2da3de2d2bf1a693b74c33d25a02a7bcc6e8fee6f0fc5ff770 WHIRLPOOL 780a2d43fb134a3d53340f84396dbe83c096ea394ad04b4c24b8cab3ef8ab88f94449ae4497951f9018d775aed04fd16db84c81c5954124497d375e74067634a
+MISC ChangeLog-2015 5316 SHA256 a8577ca1e2b89d26e3e133ed9b627023fdc233d0bb0af0047fba8e53825813a4 SHA512 ab98f85ba061e41fc5f741616eadee8fc61336aa63e67eaf110f1e29321c5f8da9d96bdbca01a5a3d96b6e4ab6549669b545d661142002143bc9a51d39bdad7a WHIRLPOOL 1c8ae5813c96550c6c1f71cbcebce8d5bcc4b9fab43116eb8e8afd83bd5a6bfe49f7139e0b28494c1869bab6ce00b63643e5d581270ed685572b92bd6a96f4db
+MISC metadata.xml 1219 SHA256 272c19796e1dd176a3960826d7a1695d5174335eced7d485a1aee158c79a6317 SHA512 23bddced94702b936cadbaf9a6a51cfd8506715a766cbef9dbb0fb69bf02443e0c8636b6237f98fd3922d0c43fb17c7c2850074e6bdefc2c9af3731a01971f8f WHIRLPOOL 865fbc0a2307a65405fb70a08e8be7085f18535a99570b709a1818c541cfc10e33858fffe66d2522ef11709ff8f8f6e8e9030cf988a1fc0be45c9c97892b5143
diff --git a/net-dns/rbldnsd/files/confd-0.997a b/net-dns/rbldnsd/files/confd-0.997a
new file mode 100644
index 000000000000..e7abb81fbc78
--- /dev/null
+++ b/net-dns/rbldnsd/files/confd-0.997a
@@ -0,0 +1,35 @@
+# A whitespace-separated list of addresses on which to listen. The
+# syntax is "host/port", where the port defaults to 53.
+#
+# Note that by default the rbldnsd init script does not require any
+# interfaces other than lo to be "up" (see bug #439092). So if you
+# LISTEN on a non-loopback interface, you should specify a dependency
+# on that interface using rc_need. An example is given below assuming
+# that net.lan0 provides 192.168.0.1.
+#
+# rc_need="net.lan0"
+#
+# LISTEN="127.0.0.1
+# 192.168.0.1/5353"
+#
+LISTEN="localhost"
+
+
+# A whitespace-separated list of RBL zones. For the correct syntax, please
+# see the rbldnsd(8) man page. The following $ZONES will look for
+# files named "badguys.example.com" and "spammers.example.net" (in the
+# appropriate format) under /var/db/rbldnsd, and use those same names
+# for the blacklists contained therein.
+ZONES="badguys.example.com:ip4set:badguys.example.com
+ spammers.example.net:ip4tset:spammers.example.net"
+
+
+# Add any additional options for the rbldnsd daemon below. The -a and
+# -vv below are suggested for performance/security reasons. They are
+# described in the man page.
+#
+# The rootdir (-r) and PID (-p) options are passed automatically, with
+# rootdir set to /var/db/rbldnsd (where you should put your zone
+# files). The daemon will run as the rbldns user, which was created by
+# portage.
+OPTIONS="-a -vv"
diff --git a/net-dns/rbldnsd/files/initd-0.997a b/net-dns/rbldnsd/files/initd-0.997a
new file mode 100644
index 000000000000..70629b47267d
--- /dev/null
+++ b/net-dns/rbldnsd/files/initd-0.997a
@@ -0,0 +1,24 @@
+#!/sbin/openrc-run
+# Copyright 1999-2013 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+start() {
+ ebegin "Starting rbldnsd"
+
+ start-stop-daemon --start --quiet --pidfile /run/rbldnsd.pid \
+ --exec /usr/sbin/rbldnsd -- \
+ -r /var/db/rbldnsd \
+ -p /run/rbldnsd.pid \
+ $(for x in ${LISTEN}; do echo "-b ${x}"; done) \
+ ${OPTIONS} \
+ ${ZONES}
+
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping rbldnsd"
+ start-stop-daemon --stop --quiet --pidfile /run/rbldnsd.pid \
+ --exec /usr/sbin/rbldnsd
+ eend $?
+}
diff --git a/net-dns/rbldnsd/files/rbldnsd-0.997a-format-security-compile-fix.patch b/net-dns/rbldnsd/files/rbldnsd-0.997a-format-security-compile-fix.patch
new file mode 100644
index 000000000000..03da010336e3
--- /dev/null
+++ b/net-dns/rbldnsd/files/rbldnsd-0.997a-format-security-compile-fix.patch
@@ -0,0 +1,30 @@
+From 5d3455065f84fe1ef4673552a27d2e6e8f02c97a Mon Sep 17 00:00:00 2001
+From: Michael Orlitzky <michael@orlitzky.com>
+Date: Mon, 22 Sep 2014 10:09:27 -0400
+Subject: [PATCH 1/1] Fix compilation with -Werror=format-security.
+
+The dslog() function takes an optional format string, analogous to
+e.g. printf(), and a list of arguments to be substituted into the
+format string. A call to dslog() in do_reload() omitted the format
+string causing GCC to throw a format-security warning. To silence the
+warning, a trivial format string of "%s" was provided.
+---
+ rbldnsd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rbldnsd.c b/rbldnsd.c
+index abf1d01..e791231 100644
+--- a/rbldnsd.c
++++ b/rbldnsd.c
+@@ -959,7 +959,7 @@ static int do_reload(int do_fork) {
+ # undef kb
+ }
+ #endif /* NO_MEMINFO */
+- dslog(LOG_INFO, 0, ibuf);
++ dslog(LOG_INFO, 0, "%s", ibuf);
+
+ check_expires();
+
+--
+1.8.5.5
+
diff --git a/net-dns/rbldnsd/files/rbldnsd-0.997a-robust-ipv6-test-support.patch b/net-dns/rbldnsd/files/rbldnsd-0.997a-robust-ipv6-test-support.patch
new file mode 100644
index 000000000000..e1ac1535dc99
--- /dev/null
+++ b/net-dns/rbldnsd/files/rbldnsd-0.997a-robust-ipv6-test-support.patch
@@ -0,0 +1,329 @@
+diff --git a/NEWS b/NEWS
+index 8d8bdd9..4d8c01d 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,19 @@
+ This file describes user-visible changes in rbldnsd.
+ Newer news is at the top.
+
++Next release
++
++ - fix tests for systems without ipv6 support, or when ipv6 is
++ disabled in rbldnsd at compile-time
++
++ - fix tests for API change in pydns >= 2.3.6
++
++ - It is no longer an error to request binding to a particular
++ address/port more than once. (The subsequent requests are simply
++ ignored.) (This avoids confusion on certain systems/configurations
++ where gethostbyname("localhost") can return 127.0.0.1 multiple
++ times.)
++
+ 0.997a (23 Jul 2013)
+
+ - minor fixes/changes in packaging, no code changes.
+diff --git a/rbldnsd.c b/rbldnsd.c
+index abf1d01..8322bdd 100644
+--- a/rbldnsd.c
++++ b/rbldnsd.c
+@@ -203,10 +203,79 @@ static volatile int signalled;
+ #define SIGNALLED_ZSTATS 0x10
+ #define SIGNALLED_TERM 0x20
+
++static inline int sockaddr_in_equal(const struct sockaddr_in *addr1,
++ const struct sockaddr_in *addr2)
++{
++ return (addr1->sin_port == addr2->sin_port
++ && addr1->sin_addr.s_addr == addr2->sin_addr.s_addr);
++}
++
++#ifndef NO_IPv6
++static inline int sockaddr_in6_equal(const struct sockaddr_in6 *addr1,
++ const struct sockaddr_in6 *addr2)
++{
++ if (memcmp(addr1->sin6_addr.s6_addr, addr2->sin6_addr.s6_addr, 16) != 0)
++ return 0;
++ return (addr1->sin6_port == addr2->sin6_port
++ && addr1->sin6_flowinfo == addr2->sin6_flowinfo
++ && addr1->sin6_scope_id == addr2->sin6_scope_id);
++}
++#endif
++
++static inline int sockaddr_equal(const struct sockaddr *addr1,
++ const struct sockaddr *addr2)
++{
++ if (addr1->sa_family != addr2->sa_family)
++ return 0;
++ switch (addr1->sa_family) {
++ case AF_INET:
++ return sockaddr_in_equal((const struct sockaddr_in *)addr1,
++ (const struct sockaddr_in *)addr2);
++#ifndef NO_IPv6
++ return sockaddr_in6_equal((const struct sockaddr_in6 *)addr1,
++ (const struct sockaddr_in6 *)addr2);
++#endif
++ default:
++ error(0, "unknown address family (%d)", addr1->sa_family);
++ }
++}
++
++/* already_bound(addr, addrlen)
++ *
++ * Determine whether we've already bound to a particular address.
++ * This is here mostly to deal with the fact that on certain systems,
++ * gethostbyname()/getaddrinfo() can return a duplicate 127.0.0.1
++ * for 'localhost'. See
++ * - https://sourceware.org/bugzilla/show_bug.cgi?id=4980
++ * - https://bugzilla.redhat.com/show_bug.cgi?id=496300
++ */
++static int already_bound(const struct sockaddr *addr, socklen_t addrlen) {
++#ifdef NO_IPv6
++ struct sockaddr_in addr_buf;
++#else
++ struct sockaddr_in6 addr_buf;
++#endif
++ struct sockaddr *boundaddr = (struct sockaddr *)&addr_buf;
++ socklen_t buflen;
++ int i;
++
++ for (i = 0; i < numsock; i++) {
++ buflen = sizeof(addr_buf);
++ if (getsockname(sock[i], boundaddr, &buflen) < 0)
++ error(errno, "getsockname failed");
++ if (buflen == addrlen && sockaddr_equal(boundaddr, addr))
++ return 1;
++ }
++ return 0;
++}
++
+ #ifdef NO_IPv6
+ static void newsocket(struct sockaddr_in *sin) {
+ int fd;
+ const char *host = ip4atos(ntohl(sin->sin_addr.s_addr));
++
++ if (already_bound((struct sockaddr *)sin, sizeof(*sin)))
++ return;
+ if (numsock >= MAXSOCK)
+ error(0, "too many listening sockets (%d max)", MAXSOCK);
+ fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+@@ -223,6 +292,8 @@ static int newsocket(struct addrinfo *ai) {
+ int fd;
+ char host[NI_MAXHOST], serv[NI_MAXSERV];
+
++ if (already_bound(ai->ai_addr, ai->ai_addrlen))
++ return 1;
+ if (numsock >= MAXSOCK)
+ error(0, "too many listening sockets (%d max)", MAXSOCK);
+ fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+diff --git a/rbldnsd.py b/rbldnsd.py
+index 9300ef2..4b78dee 100644
+--- a/rbldnsd.py
++++ b/rbldnsd.py
+@@ -2,6 +2,7 @@
+
+
+ """
++import errno
+ from itertools import count
+ import subprocess
+ from tempfile import NamedTemporaryFile, TemporaryFile
+@@ -12,6 +13,14 @@ try:
+ import DNS
+ except ImportError:
+ raise RuntimeError("The pydns library is not installed")
++try:
++ from DNS import SocketError as DNS_SocketError
++except ImportError:
++ class DNS_SocketError(Exception):
++ """ Dummy, never raised.
++
++ (Older versions of pydns before 2.3.6 do not raise SocketError.)
++ """
+
+ DUMMY_ZONE_HEADER = """
+ $SOA 0 example.org. hostmaster.example.com. 0 1h 1h 2d 1h
+@@ -113,7 +122,6 @@ class Rbldnsd(object):
+ stderr=self.stderr)
+
+ # wait for rbldnsd to start responding
+- time.sleep(0.1)
+ for retry in count():
+ if daemon.poll() is not None:
+ raise DaemonError(
+@@ -124,12 +132,18 @@ class Rbldnsd(object):
+ break
+ except QueryRefused:
+ break
++ except DNS_SocketError as ex:
++ # pydns >= 2.3.6
++ wrapped_error = ex.args[0]
++ if wrapped_error.errno != errno.ECONNREFUSED:
++ raise
+ except DNS.DNSError as ex:
++ # pydns < 2.3.6
+ if str(ex) != 'no working nameservers found':
+ raise
+- elif retries > 10:
+- raise DaemonError(
+- "rbldnsd does not seem to be responding")
++ if retry > 10:
++ raise DaemonError("rbldnsd does not seem to be responding")
++ time.sleep(0.1)
+
+ def _stop_daemon(self):
+ daemon = self._daemon
+@@ -150,6 +164,22 @@ class Rbldnsd(object):
+ raise DaemonError("rbldnsd exited with code %d"
+ % daemon.returncode)
+
++ @property
++ def no_ipv6(self):
++ """ Was rbldnsd compiled with -DNO_IPv6?
++ """
++ # If rbldnsd was compiled with -DNO_IPv6, the (therefore
++ # unsupported) '-6' command-line switch will not be described
++ # in the help message
++ cmd = [self.daemon_bin, '-h']
++ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
++ help_message = proc.stdout.readlines()
++ if proc.wait() != 0:
++ raise subprocess.CalledProcessError(proc.returncode, cmd)
++ return not any(line.lstrip().startswith('-6 ')
++ for line in help_message)
++
++
+ class TestRbldnsd(unittest.TestCase):
+ def test(self):
+ rbldnsd = Rbldnsd()
+diff --git a/test_acl.py b/test_acl.py
+index d93ca0a..10bed1c 100644
+--- a/test_acl.py
++++ b/test_acl.py
+@@ -1,5 +1,8 @@
+ """ Tests for the acl dataset
+ """
++from functools import wraps
++import socket
++import sys
+ from tempfile import NamedTemporaryFile
+ import unittest
+
+@@ -9,6 +12,35 @@ __all__ = [
+ 'TestAclDataset',
+ ]
+
++try:
++ from unittest import skipIf
++except ImportError:
++ # hokey replacement (for python <= 2.6)
++ def skipIf(condition, reason):
++ if condition:
++ def decorate(f):
++ @wraps(f)
++ def skipped(*args, **kw):
++ sys.stderr.write("skipped test: %s " % reason)
++ return skipped
++ return decorate
++ else:
++ return lambda f: f
++
++def _have_ipv6():
++ # Check for IPv6 support
++ if not getattr(socket, 'has_ipv6', False):
++ return False # no python support for ipv6
++ elif Rbldnsd().no_ipv6:
++ return False # rbldnsd compiled with -DNO_IPv6
++ try:
++ socket.socket(socket.AF_INET6, socket.SOCK_DGRAM).close()
++ except socket.error:
++ return False # no kernel (or libc) support for ipv6?
++ return True
++
++no_ipv6 = not _have_ipv6()
++
+ def daemon(acl, addr='localhost'):
+ """ Create an Rbldnsd instance with given ACL
+ """
+@@ -33,11 +65,13 @@ class TestAclDataset(unittest.TestCase):
+ addr='127.0.0.1') as dnsd:
+ self.assertEqual(dnsd.query('test.example.com'), 'Success')
+
++ @skipIf(no_ipv6, "IPv6 unsupported")
+ def test_refuse_ipv6(self):
+ with daemon(acl=["::1 :refuse"],
+ addr='::1') as dnsd:
+ self.assertRaises(QueryRefused, dnsd.query, 'test.example.com')
+
++ @skipIf(no_ipv6, "IPv6 unsupported")
+ def test_pass_ipv6(self):
+ with daemon(acl=[ "0/0 :refuse",
+ "0::1 :pass" ],
+diff --git a/test_ip4trie.py b/test_ip4trie.py
+index fe9e78f..2cce09b 100644
+--- a/test_ip4trie.py
++++ b/test_ip4trie.py
+@@ -9,7 +9,7 @@ __all__ = [
+ ]
+
+ def ip4trie(zone_data):
+- """ Run rbldnsd with an ip6trie dataset
++ """ Run rbldnsd with an ip4trie dataset
+ """
+ dnsd = Rbldnsd()
+ dnsd.add_dataset('ip4trie', ZoneFile(zone_data))
+diff --git a/test_ip6trie.py b/test_ip6trie.py
+index d3600db..377c5dd 100644
+--- a/test_ip6trie.py
++++ b/test_ip6trie.py
+@@ -15,15 +15,6 @@ def ip6trie(zone_data):
+ dnsd.add_dataset('ip6trie', ZoneFile(zone_data))
+ return dnsd
+
+-def rfc3152(ip6addr, domain='example.com'):
+- from socket import inet_pton, AF_INET6
+- from struct import unpack
+-
+- bytes = unpack("16B", inet_pton(AF_INET6, ip6addr))
+- nibbles = '.'.join("%x.%x" % (byte & 0xf, (byte >> 4) & 0xf)
+- for byte in reversed(bytes))
+- return "%s.%s" % (nibbles, domain)
+-
+ class TestIp6TrieDataset(unittest.TestCase):
+ def test_exclusion(self):
+ with ip6trie(["dead::/16 listed",
+@@ -31,5 +22,35 @@ class TestIp6TrieDataset(unittest.TestCase):
+ self.assertEqual(dnsd.query(rfc3152("dead::beef")), None)
+ self.assertEqual(dnsd.query(rfc3152("dead::beee")), "listed")
+
++
++def rfc3152(ip6addr, domain='example.com'):
++ return "%s.%s" % ('.'.join(reversed(_to_nibbles(ip6addr))), domain)
++
++def _to_nibbles(ip6addr):
++ """ Convert ip6 address (in rfc4291 notation) to a sequence of nibbles
++
++ NB: We avoid the use of socket.inet_pton(AF_INET6, ip6addr) here
++ because it fails (with 'error: can't use AF_INET6, IPv6 is
++ disabled') when python has been compiled without IPv6 support. See
++ http://www.corpit.ru/pipermail/rbldnsd/2013q3/001181.html
++
++ """
++ def _split_words(addr):
++ return [ int(w, 16) for w in addr.split(':') ] if addr else []
++
++ if '::' in ip6addr:
++ head, tail = [ _split_words(s) for s in ip6addr.split('::', 1) ]
++ nzeros = 8 - len(head) - len(tail)
++ assert nzeros >= 0
++ words = head + [ 0 ] * nzeros + tail
++ else:
++ words = _split_words(ip6addr)
++
++ assert len(words) == 8
++ for word in words:
++ assert 0 <= word <= 0xffff
++
++ return ''.join("%04x" % word for word in words)
++
+ if __name__ == '__main__':
+ unittest.main()
diff --git a/net-dns/rbldnsd/files/rbldnsd-0.998-fix-huge-zone-OOM.patch b/net-dns/rbldnsd/files/rbldnsd-0.998-fix-huge-zone-OOM.patch
new file mode 100644
index 000000000000..7a4d2da7187f
--- /dev/null
+++ b/net-dns/rbldnsd/files/rbldnsd-0.998-fix-huge-zone-OOM.patch
@@ -0,0 +1,60 @@
+This upstream patch has been merged but not released. I (mjo) dropped
+a change to the NEWS file to prevent a pointless conflict.
+
+From a1295eefc78b6e8a3c220e164dbfad6dbecc6f6e Mon Sep 17 00:00:00 2001
+From: Antonio Mammita <am@spamteq.com>
+Date: Wed, 21 Dec 2016 16:54:06 +0100
+Subject: [PATCH] Fix for out of memory errors on huge zones. Thanks to Andrew
+ Clayton
+
+---
+ rbldnsd.h | 6 +++---
+ rbldnsd_util.c | 6 +++---
+ 3 files changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/rbldnsd.h b/rbldnsd.h
+index 6acd8a0..f195a30 100644
+--- a/rbldnsd.h
++++ b/rbldnsd.h
+@@ -367,9 +367,9 @@ extern struct dataset *g_dsacl; /* global acl */
+ extern const char *show_version; /* version.bind CH TXT */
+
+ void oom(void);
+-char *emalloc(unsigned size);
+-char *ezalloc(unsigned size); /* zero-fill */
+-char *erealloc(void *ptr, unsigned size);
++char *emalloc(size_t size);
++char *ezalloc(size_t size); /* zero-fill */
++char *erealloc(void *ptr, size_t size);
+ char *estrdup(const char *str);
+ char *ememdup(const void *buf, unsigned size);
+
+diff --git a/rbldnsd_util.c b/rbldnsd_util.c
+index d17b51b..c6d628d 100644
+--- a/rbldnsd_util.c
++++ b/rbldnsd_util.c
+@@ -460,21 +460,21 @@ dump_a_txt(const char *name, const char *rr,
+
+ #endif
+
+-char *emalloc(unsigned size) {
++char *emalloc(size_t size) {
+ void *ptr = malloc(size);
+ if (!ptr)
+ oom();
+ return ptr;
+ }
+
+-char *ezalloc(unsigned size) {
++char *ezalloc(size_t size) {
+ void *ptr = calloc(1, size);
+ if (!ptr)
+ oom();
+ return ptr;
+ }
+
+-char *erealloc(void *ptr, unsigned size) {
++char *erealloc(void *ptr, size_t size) {
+ void *nptr = realloc(ptr, size);
+ if (!nptr)
+ oom();
diff --git a/net-dns/rbldnsd/metadata.xml b/net-dns/rbldnsd/metadata.xml
new file mode 100644
index 000000000000..6ae7879eb421
--- /dev/null
+++ b/net-dns/rbldnsd/metadata.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="person">
+ <email>mjo@gentoo.org</email>
+ <name>Michael Orlitzky</name>
+ </maintainer>
+
+ <longdescription lang="en">
+ rbldnsd is a small and fast DNS daemon which is especially made to
+ serve DNSBL zones. This daemon was inspired by Dan J. Bernstein's
+ rbldns program found in the djbdns package.
+
+ rbldnsd is extremely fast - it outperforms both bind and djbdns
+ greatly. It has very small memory footprint.
+
+ The daemon can serve both IP-based (ordb.org, dsbl.org etc) and
+ name-based (rfc-ignorant.org) blocklists. Unlike DJB's rbldns, it
+ has ability to specify individual values for every entry, can
+ serve as many zones on a single IP address as you wish, and,
+ finally, it is a real nameserver: it can reply to DNS metadata
+ requests. The daemon keeps all zones in memory for faster
+ operations, but its memory usage is very efficient, especially for
+ repeated TXT values which are stored only once.
+ </longdescription>
+
+ <upstream>
+ <remote-id type="github">spamhaus/rbldnsd</remote-id>
+ </upstream>
+</pkgmetadata>
diff --git a/net-dns/rbldnsd/rbldnsd-0.998-r2.ebuild b/net-dns/rbldnsd/rbldnsd-0.998-r2.ebuild
new file mode 100644
index 000000000000..04537f305756
--- /dev/null
+++ b/net-dns/rbldnsd/rbldnsd-0.998-r2.ebuild
@@ -0,0 +1,67 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+PYTHON_COMPAT=( python2_7 )
+
+inherit toolchain-funcs user python-any-r1
+
+DESCRIPTION="DNS server designed to serve blacklist zones"
+HOMEPAGE="https://rbldnsd.io/"
+SRC_URI="https://github.com/spamhaus/${PN}/archive/${PV}.tar.gz -> ${P}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~hppa ~sparc ~x86 ~x86-fbsd"
+IUSE="ipv6 test zlib"
+
+RDEPEND="zlib? ( sys-libs/zlib )"
+DEPEND="${RDEPEND}
+ test? (
+ ${PYTHON_DEPS}
+ $(python_gen_any_dep 'dev-python/pydns:2[${PYTHON_USEDEP}]')
+ )"
+
+PATCHES=(
+ "${FILESDIR}/rbldnsd-0.997a-robust-ipv6-test-support.patch"
+ "${FILESDIR}/rbldnsd-0.997a-format-security-compile-fix.patch"
+ "${FILESDIR}/rbldnsd-0.998-fix-huge-zone-OOM.patch"
+)
+
+src_configure() {
+ # The ./configure file is handwritten and doesn't support a `make
+ # install` target, so there are no --prefix options. The econf
+ # function appends those automatically, so we can't use it.
+ ./configure \
+ $(use_enable ipv6) \
+ $(use_enable zlib) \
+ || die "./configure failed"
+}
+
+src_compile() {
+ emake \
+ AR="$(tc-getAR)" \
+ CC="$(tc-getCC)" \
+ RANLIB="$(tc-getRANLIB)"
+}
+
+src_test() {
+ emake check \
+ CC="$(tc-getCC)" \
+ PYTHON="${PYTHON}"
+}
+
+src_install() {
+ einstalldocs
+ dosbin rbldnsd
+ doman rbldnsd.8
+ keepdir /var/db/rbldnsd
+ newinitd "${FILESDIR}"/initd-0.997a rbldnsd
+ newconfd "${FILESDIR}"/confd-0.997a rbldnsd
+}
+
+pkg_postinst() {
+ enewgroup rbldns
+ enewuser rbldns -1 -1 /var/db/rbldnsd rbldns
+ fowners rbldns:rbldns /var/db/rbldnsd
+}
diff --git a/net-dns/rbldnsd/rbldnsd-0.998.ebuild b/net-dns/rbldnsd/rbldnsd-0.998.ebuild
new file mode 100644
index 000000000000..8c559177fb0e
--- /dev/null
+++ b/net-dns/rbldnsd/rbldnsd-0.998.ebuild
@@ -0,0 +1,66 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=5
+PYTHON_COMPAT=( python2_7 )
+
+inherit eutils toolchain-funcs user python-any-r1
+
+DESCRIPTION="DNS server designed to serve blacklist zones"
+HOMEPAGE="http://www.corpit.ru/mjt/rbldnsd.html"
+SRC_URI="http://www.corpit.ru/mjt/rbldnsd/${P}.tar.gz"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="amd64 hppa ~sparc x86 ~x86-fbsd"
+IUSE="ipv6 test zlib"
+
+RDEPEND="zlib? ( sys-libs/zlib )"
+DEPEND="${RDEPEND}
+ test? (
+ ${PYTHON_DEPS}
+ $(python_gen_any_dep 'dev-python/pydns:2[${PYTHON_USEDEP}]')
+ )"
+
+src_prepare() {
+ epatch "${FILESDIR}/rbldnsd-0.997a-robust-ipv6-test-support.patch"
+ epatch "${FILESDIR}/rbldnsd-0.997a-format-security-compile-fix.patch"
+}
+
+src_configure() {
+ # The ./configure file is handwritten and doesn't support a `make
+ # install` target, so there are no --prefix options. The econf
+ # function appends those automatically, so we can't use it.
+ ./configure \
+ $(use_enable ipv6) \
+ $(use_enable zlib) \
+ || die "./configure failed"
+}
+
+src_compile() {
+ emake \
+ AR="$(tc-getAR)" \
+ CC="$(tc-getCC)" \
+ RANLIB="$(tc-getRANLIB)"
+}
+
+src_test() {
+ emake check \
+ CC="$(tc-getCC)" \
+ PYTHON="${PYTHON}"
+}
+
+src_install() {
+ dosbin rbldnsd
+ doman rbldnsd.8
+ keepdir /var/db/rbldnsd
+ dodoc CHANGES* TODO NEWS README*
+ newinitd "${FILESDIR}"/initd-0.997a rbldnsd
+ newconfd "${FILESDIR}"/confd-0.997a rbldnsd
+}
+
+pkg_postinst() {
+ enewgroup rbldns
+ enewuser rbldns -1 -1 /var/db/rbldnsd rbldns
+ chown rbldns:rbldns /var/db/rbldnsd
+}