From a863daff6844e330183045f513dcc1b421af426c Mon Sep 17 00:00:00 2001
From: Daniel Mack <zonque@gmail.com>
Date: Wed, 13 Jul 2011 00:30:53 +0200
Subject: inet/resolv: add res_mkquery

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 libc/inet/Makefile.in |   2 +-
 libc/inet/res_data.c  |   8 ++++
 libc/inet/resolv.c    | 116 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 124 insertions(+), 2 deletions(-)
 create mode 100644 libc/inet/res_data.c

(limited to 'libc')

diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in
index f2a495aa5..09ba65d1a 100644
--- a/libc/inet/Makefile.in
+++ b/libc/inet/Makefile.in
@@ -41,7 +41,7 @@ CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \
 	res_init.c res_query.c res_comp.c ns_name.c \
 	_res_state.c
 CSRC-$(findstring y,$(UCLIBC_HAS_RESOLVER_SUPPORT)) += \
-	ns_netint.c ns_parse.c
+	ns_netint.c ns_parse.c res_data.c
 ## # unused ATM
 ## CSRC-y += encodep.c decodep.c formquery.c
 
diff --git a/libc/inet/res_data.c b/libc/inet/res_data.c
new file mode 100644
index 000000000..b554b93db
--- /dev/null
+++ b/libc/inet/res_data.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_res_data
+#include RESOLVER
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 011cd5e56..627423b39 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -4081,6 +4081,120 @@ int ns_msg_getflag(ns_msg handle, int flag) {
 }
 #endif /* L_ns_parse */
 
+#ifdef L_res_data
+int res_mkquery(int op, const char *dname, int class, int type,
+				const unsigned char *data, int datalen,
+				const unsigned char *newrr_in,
+				unsigned char *buf, int buflen)
+{
+	HEADER *hp;
+	unsigned char *cp, *ep;
+	unsigned char *dnptrs[20], **dpp, **lastdnptr;
+	uint32_t _res_options;
+	int n;
+
+	if (!buf || buflen < HFIXEDSZ) {
+		h_errno = NETDB_INTERNAL;
+		return -1;
+	}
+
+ again:
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_options = _res.options;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if (!(_res_options & RES_INIT)) {
+		res_init(); /* our res_init never fails */
+		goto again;
+	}
+
+#ifdef DEBUG
+	if (_res_options & RES_DEBUG)
+		printf(";; res_mkquery(%d, %s, %s, %d, %d)\n",
+			   name, (op, dname ? dname : "<Nil>"), class, type);
+#endif
+
+	memset(buf, 0, HFIXEDSZ);
+	hp = (HEADER *) buf;
+	hp->id = getpid() & 0xffff;
+	hp->opcode = op;
+	hp->rd = (_res.options & RES_RECURSE) != 0U;
+	hp->rcode = NOERROR;
+
+	cp = buf + HFIXEDSZ;
+	ep = buf + buflen;
+	dpp = dnptrs;
+	*dpp++ = buf;
+	*dpp++ = NULL;
+	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+	/*
+	 * perform opcode specific processing
+	 */
+	switch (op) {
+	case QUERY:
+	case NS_NOTIFY_OP:
+		if (ep - cp < QFIXEDSZ)
+			return -1;
+
+		if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr)) < 0)
+			return -1;
+
+		cp += n;
+		NS_PUT16(type, cp);
+		NS_PUT16(class, cp);
+		hp->qdcount = htons(1);
+
+		if (op == QUERY || data == NULL)
+			break;
+
+		/*
+		 * Make an additional record for completion domain.
+		 */
+		if ((ep - cp) < RRFIXEDSZ)
+			return -1;
+
+		n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+					 dnptrs, lastdnptr);
+		if (n < 0)
+			return -1;
+
+		cp += n;
+		NS_PUT16(T_NULL, cp);
+		NS_PUT16(class, cp);
+		NS_PUT32(0, cp);
+		NS_PUT16(0, cp);
+		hp->arcount = htons(1);
+
+		break;
+
+	case IQUERY:
+		/*
+		 * Initialize answer section
+		 */
+		if (ep - cp < 1 + RRFIXEDSZ + datalen)
+			return -1;
+
+		*cp++ = '\0';   /*%< no domain name */
+		NS_PUT16(type, cp);
+		NS_PUT16(class, cp);
+		NS_PUT32(0, cp);
+		NS_PUT16(datalen, cp);
+
+		if (datalen) {
+			memcpy(cp, data, (size_t)datalen);
+			cp += datalen;
+		}
+
+		hp->ancount = htons(1);
+		break;
+
+	default:
+		return -1;
+	}
+
+	return cp - buf;
+}
+#endif /* L_res_data */
+
 /* Unimplemented: */
-/* res_mkquery */
 /* res_send */
-- 
cgit v1.2.3