about summary refs log tree commit diff
path: root/src/network/lookup_name.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/lookup_name.c')
-rw-r--r--src/network/lookup_name.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
index e1b583ee..83c0fc27 100644
--- a/src/network/lookup_name.c
+++ b/src/network/lookup_name.c
@@ -9,7 +9,6 @@
 #include "lookup.h"
 #include "stdio_impl.h"
 #include "syscall.h"
-#include "__dns.h"
 
 static int is_valid_hostname(const char *host)
 {
@@ -86,30 +85,71 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
 	return cnt;
 }
 
-static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
+struct dpc_ctx {
+	struct address *addrs;
+	char *canon;
+	int cnt;
+};
+
+int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *);
+int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int);
+int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int);
+int __res_msend(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int);
+
+#define RR_A 1
+#define RR_CNAME 5
+#define RR_AAAA 28
+
+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
 {
-	unsigned char reply[1024] = { 0 }, *p = reply;
 	char tmp[256];
-	int i, cnt = 0;
-
-	/* Perform one or more DNS queries for host */
-	int result = __dns_query(reply, name, family, 0);
-	if (result < 0) return result;
+	struct dpc_ctx *ctx = c;
+	switch (rr) {
+	case RR_A:
+		if (len != 4) return -1;
+		ctx->addrs[ctx->cnt].family = AF_INET;
+		memcpy(ctx->addrs[ctx->cnt++].addr, data, 4);
+		break;
+	case RR_AAAA:
+		if (len != 16) return -1;
+		ctx->addrs[ctx->cnt].family = AF_INET6;
+		memcpy(ctx->addrs[ctx->cnt++].addr, data, 16);
+		break;
+	case RR_CNAME:
+		if (__dn_expand(packet, (const unsigned char *)packet + 512,
+		    data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
+			strcpy(ctx->canon, tmp);
+		break;
+	}
+	return 0;
+}
 
-	for (i=0; i<result; i++) {
-		if (family != AF_INET6) {
-			int j = __dns_get_rr(&buf[cnt].addr, sizeof *buf, 4, MAXADDRS-cnt, p, RR_A, 0);
-			while (j--) buf[cnt++].family = AF_INET;
-		}
-		if (family != AF_INET) {
-			int j = __dns_get_rr(&buf[cnt].addr, sizeof *buf, 16, MAXADDRS-cnt, p, RR_AAAA, 0);
-			while (j--) buf[cnt++].family = AF_INET6;
-		}
-		p += 512;
+static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
+{
+	unsigned char qbuf[2][280], abuf[2][512];
+	const unsigned char *qp[2] = { qbuf[0], qbuf[1] };
+	unsigned char *ap[2] = { abuf[0], abuf[1] };
+	int qlens[2], alens[2];
+	int i, nq = 0;
+	struct dpc_ctx ctx = { .addrs = buf, .canon = canon };
+
+	if (family != AF_INET6) {
+		qlens[nq] = __res_mkquery(0, name, 1, RR_A, 0, 0, 0,
+			qbuf[nq], sizeof *qbuf);
+		nq++;
 	}
-	__dns_get_rr(tmp, 0, 256, 1, reply, RR_CNAME, 1);
-	if (is_valid_hostname(tmp)) strcpy(canon, tmp);
-	return cnt;
+	if (family != AF_INET) {
+		qlens[nq] = __res_mkquery(0, name, 1, RR_AAAA, 0, 0, 0,
+			qbuf[nq], sizeof *qbuf);
+		nq++;
+	}
+
+	if (__res_msend(nq, qp, qlens, ap, alens, sizeof *abuf) < 0) return EAI_SYSTEM;
+
+	for (i=0; i<nq; i++)
+		__dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
+
+	return ctx.cnt;
 }
 
 int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags)