Dnsmasq resolution issue with 464xlat and 4G

Hi All,

I am configuring 464XLAT on my router and encountered an issue. The specific requirement for 464XLAT is that ipv4only.arpa needs to be resolved by a DNS64 server as both IPv4 and IPv6.

My router has wan, 4g1, and 4g2 interfaces. Below is the network configuration:

config interface 'wan'
    option device 'wan'
    option proto 'dhcp'
    option metric '1'
    option dns_metric '20'

config interface '4g1'
    option metric '40'
    option proto '3g'
    option device '/dev/ttyUSB1'
    option service 'umts'
    list dns '2606:4700:4700::64'
    list dns '2606:4700:4700::6400'
    option peerdns '0'
    option auto '0'
    option ipv6 'auto'
    option dns_metric '10'

config interface '4g2'
    option metric '41'
    option proto '3g'
    option device '/dev/ttyUSB4'
    option service 'umts'
    list dns '2606:4700:4700::64'
    list dns '2606:4700:4700::6400'
    option peerdns '0'
    option pdp_context 'IPV6'
    option ipv6 'auto'
    option dns_metric '5'

With the above configuration, when I try to run nslookup, I get:

NEAdmin@NE-25:~# nslookup ipv4only.arpa 
Server:         127.0.0.1
Address:        127.0.0.1#53

Name:      ipv4only.arpa
Address 1: 192.0.0.171
Address 2: 192.0.0.170
*** Can't find ipv4only.arpa: No answer

If I disable the wan interface, the result changes to:

NEAdmin@NE-25:~# nslookup ipv4only.arpa 
Server:         127.0.0.1
Address:        127.0.0.1#53

Name:      ipv4only.arpa
Address 1: 192.0.0.171
Address 2: 192.0.0.170
Address 3: 64:ff9b::c000:ab
Address 4: 64:ff9b::c000:aa

Here is the content of the resolv.conf file:

NEAdmin@NE-25:~# cat /tmp/resolv.conf.d/resolv.conf.auto 
# Interface 4g2_6
# Interface 4g2
nameserver 2606:4700:4700::64
nameserver 2606:4700:4700::6400
# Interface wan
nameserver 8.8.8.8
nameserver 1.1.1.1

Due to this, 464xlatcfg fails to resolve ipv4only.arpa and ignores the 464XLAT configuration.
We have already setted dns weight to prefer 4g2 which has ipv6 dns server, but its still preferring ipv4 only.

Any help or suggestions to resolve this issue would be greatly appreciated.

Thank you!

Set peerdns 0 on wan as well.

@mk24
thanks for the reply,
i have checked with setting peerdns 0 on wan, but after that dns resolution is failing if only wan is there, setting custom dns on wan as well prefers ipv4 address only

It's not clear what your intentions are with the multiple WANs. Especially considering that the LTEs are v6 only and the wired one is v4 only it's going to be complicated.

If you don't have a v6 connection then the Google DNS64 will be unreachable of course. dnsmasq only considers the whole list in a failover / round robin fashion. DNS servers aren't attached to a particular interface-- every list dns merely adds them to the flat list in the file no matter where it appears.

I ended up fixing the issue by modifying 464xlatcfg.c. Instead of just doing a simple DNS lookup using getaddrinfo(), I looped through resolv.conf.auto and did the lookup with the first IPv6 DNS server I found.

But things went sideways when I tried to do that. It turns out musl doesn’t support setting resolver options per process using res_ninit, so I ended up using the nslookup tool and parsing the output instead.

Posting patch if anyone looks for solution. not a good one but works.
suggest if routing can be optimized anyway

diff --git a/package/network/ipv6/464xlat/src/464xlatcfg.c b/package/network/ipv6/464xlat/src/464xlatcfg.c
--- a/package/network/ipv6/464xlat/src/464xlatcfg.c
+++ b/package/network/ipv6/464xlat/src/464xlatcfg.c
@@ -23,6 +23,7 @@
 #include <signal.h>
 #include <stdio.h>
 #include <netdb.h>
+#include <string.h>
 
 static void sighandler(__attribute__((unused)) int signal)
 {
@@ -60,19 +61,61 @@ int main(int argc, const char *argv[])
 
 	prefix[sizeof(prefix) - 1] = 0;
 	strncpy(prefix, argv[3], sizeof(prefix) - 1);
-
+/*
+ * Reimplemented 464xlatcfg to force resolve against DNS64 server
+ * Workaround - We are parsing /tmp/resolv.conf.d/resolv.conf.auto for IPv6 DNS server
+ * and resolving with nslookup tool as musl doesn't support setting up resolvconf option
+ * per process basis with res_ninit
+ */
 	if (!prefix[0]) {
-		struct addrinfo hints = { .ai_family = AF_INET6 }, *res;
-		if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res) {
-			sleep(3);
-			if (getaddrinfo("ipv4only.arpa", NULL, &hints, &res) || !res)
-				return 2;
+		FILE *resolv_fp = fopen("/tmp/resolv.conf.d/resolv.conf.auto", "r");
+		if (!resolv_fp) {
+			fprintf(stderr, "Failed to open /tmp/resolv.conf.d/resolv.conf.auto\n");
+			return 2;
+		}
+
+		char line[256];
+		char dns_server[INET6_ADDRSTRLEN];
+		int found_ipv6_dns = 0;
+
+		while (fgets(line, sizeof(line), resolv_fp)) {
+			if (sscanf(line, "nameserver %45[0-9a-fA-F:.]", dns_server) == 1) {
+				if (strchr(dns_server, ':')) {
+					found_ipv6_dns = 1;
+					break;
+				}
+			}
+		}
+
+		fclose(resolv_fp);
+
+		if (!found_ipv6_dns) {
+			fprintf(stderr, "No IPv6 DNS server found\n");
+			return 2;
+		}
+
+		char nslookup_cmd[256];
+		snprintf(nslookup_cmd, sizeof(nslookup_cmd), "nslookup ipv4only.arpa %s", dns_server);
+		FILE *nslookup_fp = popen(nslookup_cmd, "r");
+		if (!nslookup_fp) {
+			fprintf(stderr, "Failed to run nslookup\n");
+			return 2;
+		}
+
+		while (fgets(line, sizeof(line), nslookup_fp)) {
+			if (sscanf(line, "Address 3: %45[0-9a-fA-F:.]", prefix) == 1) {
+				break;
+			}
+		}
+
+		pclose(nslookup_fp);
+
+		if (!prefix[0]) {
+			fprintf(stderr, "Failed to resolve ipv4only.arpa\n");
+			return 2;
 		}
 
-		struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)res->ai_addr;
-		inet_ntop(AF_INET6, &sin6->sin6_addr, prefix, sizeof(prefix) - 4);
 		strcat(prefix, "/96");
-		freeaddrinfo(res);
 	}
 
 	int i = 0;

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.