summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2011-07-13 00:30:53 +0200
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2011-08-26 09:29:53 +0200
commita863daff6844e330183045f513dcc1b421af426c (patch)
treeb40f4030efea275bcdca981e750601985d13338e /libc
parent5f6fe1fca1e60923503dd391a60b2ad5b9aead31 (diff)
inet/resolv: add res_mkquery
Signed-off-by: Daniel Mack <zonque@gmail.com>
Diffstat (limited to 'libc')
-rw-r--r--libc/inet/Makefile.in2
-rw-r--r--libc/inet/res_data.c8
-rw-r--r--libc/inet/resolv.c116
3 files changed, 124 insertions, 2 deletions
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 */