From 95e139d0b269f86e575b36ebca4ac7d810398246 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Mon, 6 May 2013 10:01:45 +0000
Subject: [PATCH] ipset-dns: support simultaneously populating IPv4 and IPv6
 sets

SVN-Revision: 36554
---
 .../services/ipset-dns/files/ipset-dns.config |  7 ++-
 .../services/ipset-dns/files/ipset-dns.init   |  7 ++-
 .../patches/100-simultaneous-ipv4-ipv6.patch  | 57 +++++++++++++++++++
 3 files changed, 66 insertions(+), 5 deletions(-)
 create mode 100644 package/network/services/ipset-dns/patches/100-simultaneous-ipv4-ipv6.patch

diff --git a/package/network/services/ipset-dns/files/ipset-dns.config b/package/network/services/ipset-dns/files/ipset-dns.config
index 52e87b27cc..0270366af7 100644
--- a/package/network/services/ipset-dns/files/ipset-dns.config
+++ b/package/network/services/ipset-dns/files/ipset-dns.config
@@ -1,7 +1,10 @@
 # declare an ipset-dns listener instance, multiple allowed
 config ipset-dns
-	# use given ipset
-	option ipset 'domain-filter'
+	# use given ipset for type A (IPv4) responses
+	option ipset 'domain-filter-ipv4'
+
+	# use given ipset for type AAAA (IPv6) responses
+	option ipset6 'domain-filter-ipv6'
 
 	# use given listening port
 	# defaults to 53000 + instance number
diff --git a/package/network/services/ipset-dns/files/ipset-dns.init b/package/network/services/ipset-dns/files/ipset-dns.init
index 5d41539a7b..7b732791ea 100755
--- a/package/network/services/ipset-dns/files/ipset-dns.init
+++ b/package/network/services/ipset-dns/files/ipset-dns.init
@@ -21,10 +21,11 @@ find_nameserver() {
 
 start_instance() {
 	local cfg="$1"
-	local ipset port dns
+	local ipset ipset6 port dns
 
 	config_get ipset "$cfg" ipset
-	[ -n "$ipset" ] || {
+	config_get ipset6 "$cfg" ipset6
+	[ -n "$ipset$ipset6" ] || {
 		echo "No ipset specified for instance $cfg" >&2
 		return 1
 	}
@@ -38,7 +39,7 @@ start_instance() {
 	config_get port "$cfg" port $((PORT++))
 
 	SERVICE_PID_FILE="/var/run/ipset-dns-$port.pid" \
-		service_start /usr/sbin/ipset-dns "$ipset" "$port" "$dns"
+		service_start /usr/sbin/ipset-dns "$ipset" "$ipset6" "$port" "$dns"
 }
 
 start() {
diff --git a/package/network/services/ipset-dns/patches/100-simultaneous-ipv4-ipv6.patch b/package/network/services/ipset-dns/patches/100-simultaneous-ipv4-ipv6.patch
new file mode 100644
index 0000000000..19669a05b5
--- /dev/null
+++ b/package/network/services/ipset-dns/patches/100-simultaneous-ipv4-ipv6.patch
@@ -0,0 +1,57 @@
+--- a/ipset-dns.c
++++ b/ipset-dns.c
+@@ -307,19 +307,20 @@ int main(int argc, char *argv[]) 
+ 	struct timeval tv;
+ 	char msg[512];
+ 	char ip[INET6_ADDRSTRLEN];
+-	char *ipset;
++	char *ipset, *ipset6;
+ 	int listen_sock, upstream_sock;
+ 	int pos, i, size, af;
+ 	socklen_t len;
+ 	size_t received;
+ 	pid_t child;
+ 	
+-	if (argc != 4) {
+-		fprintf(stderr, "Usage: %s ipset port upstream\n", argv[0]);
++	if (argc != 5) {
++		fprintf(stderr, "Usage: %s ipv4-ipset ipv6-ipset port upstream\n", argv[0]);
+ 		return 1;
+ 	}
+ 
+ 	ipset = argv[1];
++	ipset6 = argv[2];
+ 
+ 	listen_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ 	if (listen_sock < 0) {
+@@ -329,7 +330,7 @@ int main(int argc, char *argv[]) 
+ 
+ 	memset(&listen_addr, 0, sizeof(listen_addr));
+ 	listen_addr.sin_family = AF_INET;
+-	listen_addr.sin_port = htons(atoi(argv[2]));
++	listen_addr.sin_port = htons(atoi(argv[3]));
+ 	listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ 	i = 1;
+ 	setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+@@ -341,7 +342,7 @@ int main(int argc, char *argv[]) 
+ 	memset(&upstream_addr, 0, sizeof(upstream_addr));
+ 	upstream_addr.sin_family = AF_INET;
+ 	upstream_addr.sin_port = htons(53);
+-	inet_aton(argv[3], &upstream_addr.sin_addr);
++	inet_aton(argv[4], &upstream_addr.sin_addr);
+ 	
+ 	/* TODO: Put all of the below code in several forks all listening on the same sock. */
+ 
+@@ -434,8 +435,11 @@ int main(int argc, char *argv[]) 
+ 				continue;
+ 			}
+ 
++			if ((af == AF_INET && !*ipset) || (af == AF_INET6 && !*ipset6))
++				continue;
++
+ 			printf("%s: %s\n", answer.dotted, ip);
+-			if (add_to_ipset(ipset, answer.rdata, af) < 0)
++			if (add_to_ipset((af == AF_INET) ? ipset : ipset6, answer.rdata, af) < 0)
+ 				perror("add_to_ipset");
+ 		}
+ 		
-- 
GitLab