summaryrefslogtreecommitdiffstats
path: root/src/util/wshelper/res_quer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/wshelper/res_quer.c')
-rw-r--r--src/util/wshelper/res_quer.c561
1 files changed, 561 insertions, 0 deletions
diff --git a/src/util/wshelper/res_quer.c b/src/util/wshelper/res_quer.c
new file mode 100644
index 0000000000..7836ed9215
--- /dev/null
+++ b/src/util/wshelper/res_quer.c
@@ -0,0 +1,561 @@
+/*
+ *
+ * @doc RESOLVE
+ *
+ *
+ * @module res_quer.c | Contains the implementation of res_query,
+ * res_search, and res_querydomain
+ *
+ * WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c 5.11 (Berkeley) 3/6/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windns.h>
+
+#define MAX_MSG_SIZE 0x8000
+
+#define strcasecmp stricmp
+
+#ifdef _DEBUG
+#define DEBUG
+#endif
+int
+__hostalias(register const char *name, char* abuf);
+DNS_STATUS do_res_search(const char *name, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen);
+void __putshort(register u_short, register u_char *);
+void __putlong(register u_long, u_char *);
+int build_rr(char* p, PDNS_RECORD ptr, int qclass);
+int put_qname(char* p, char* qname);
+
+
+
+/*
+ a generic query interface to the DNS name space. The query is performed with the dnsapi and
+ the answer buffer is populated based on the returned RR set.
+
+ \param[in] name domain name
+ \param[in] qclass class of query(such as DNS_CLASS_INTERNET, DNS_CLASS_CSNET, DNS_CLASS_CHAOS,
+ DNS_CLASS_HESIOD. Defined in windns.h)
+ \param[in] type type of query(such as DNS_TYPE_A, DNS_TYPE_NS, DNS_TYPE_MX, DNS_TYPE_SRV. Defined in
+ windns.h)
+ \param[in] answer buffer to put answer in
+ \param[in] anslen size of the answer buffer. compare the anslen with the return value, if the return
+ value is bigger than anslen, it means the answer buffer doesn't contain the complete
+ response. You will need to call this function again with a bigger answer buffer if
+ you care about the complete response
+
+ \retval return the size of the response on success, -1 on error
+
+
+ */
+int WINAPI
+res_search(const char *name, int qclass, int type, u_char *answer, int anslen)
+ /* domain name, class and type of query, buffer to put answer, size of answer */
+{
+ char debstr[80];
+ int n = 0;
+ DNS_STATUS status;
+ char queryname[DNS_MAX_NAME_BUFFER_LENGTH ];
+ register const char *cp;
+ int len = 0;
+
+ char** domain;
+
+ status = -1;
+ memset(answer, 0, anslen);
+ memset(queryname, 0, sizeof(queryname));
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return (-1);
+
+ for (cp = name, n = 0; *cp; cp++)
+ if (*cp == '.')
+ n++;
+
+ if (n == 0 && !__hostalias(name, queryname) && strlen(queryname)>0)
+ {
+ status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+ if (status == 0)
+ return len;
+ }
+
+ if ((n == 0 && _res.options & RES_DEFNAMES))
+ // (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
+ {
+ for (domain = _res.dnsrch; *domain; domain++) {
+ strcpy(queryname, name);
+ strcat(queryname, ".");
+ strcat(queryname, *domain);
+ status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+ if (status == 0)
+ return len;
+ }
+ }
+
+
+ strcpy(queryname, name);
+ status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+
+
+ if (status)
+ {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ {
+ wsprintf(debstr, "res_query failed\n");
+ OutputDebugString(debstr);
+ }
+#endif
+ return -1;
+ }
+ return len;
+}
+
+int
+put_qname(char* cp, char* qname)
+{
+ char* p;
+ char* temp;
+ INT_PTR n = 0;
+ INT_PTR i = 0;
+ temp = qname;
+ while (p = strchr(temp, '.'))
+ {
+ n = p - temp;
+ if (n == 0)
+ {
+ temp++;
+ break;
+ }
+ cp[0] = (int)n;
+ cp++;
+ i++;
+ strncpy(cp, temp, n);
+ temp = p+1;
+ cp = cp + n;
+ i = i + n;
+ }
+ n = strlen(temp);
+ if (n > 0)
+ {
+ cp[0] = (int)n;
+ cp++;
+ i++;
+ strcpy(cp, temp);
+ cp = cp+n;
+ }
+ cp[0] = 0;
+ i = i+n+1;
+ return (int)i;
+}
+
+DNS_STATUS
+do_res_search(const char *queryname, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen)
+{
+ PDNS_RECORD pDnsRecord;
+ PDNS_RECORD ptr;
+ DNS_STATUS status;
+ DNS_FREE_TYPE freetype ;
+ HEADER *hp;
+ char *cp;
+ int n;
+ int i;
+ u_char answer[MAX_MSG_SIZE];
+ DWORD options = DNS_QUERY_STANDARD;
+ freetype = DnsFreeRecordListDeep;
+
+ memset(answer, 0, MAX_MSG_SIZE);
+ if (!(_res.options & RES_RECURSE))
+ options = options | DNS_QUERY_NO_RECURSION;
+ if (_res.options & RES_USEVC)
+ options = options | DNS_QUERY_USE_TCP_ONLY;
+ if (_res.options & RES_IGNTC)
+ options = options | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE;
+
+ status = DnsQuery_A(queryname, //pointer to OwnerName
+ type, //Type of the record to be queried
+ options,
+ NULL, //contains DNS server IP address
+ &pDnsRecord, //Resource record comprising the response
+ NULL); //reserved for future use
+
+ if (status)
+ return status;
+
+
+ hp = (HEADER *) answer;
+ cp = answer + sizeof(HEADER);
+
+ // populating the header
+ hp->id = htons(++_res.id); // query id
+ hp->qr = 1; // 0 for query 1 for response
+ hp->opcode = 0; // standard query
+ hp->aa = 1; // authoritative answer
+ hp->tc = 0; // no truncation
+ hp->rd = (_res.options & RES_RECURSE) != 0; // resursion desired
+ hp->ra = 1; // recursion available
+ hp->pr = (_res.options & RES_PRIMARY) != 0; // primary server required
+ hp->rcode = NOERROR;
+ hp->qdcount = htons(1); // number of question entries
+ i = put_qname(cp, (char*)queryname);
+ cp = cp + i;
+ __putshort(type, (u_char *)cp);
+ cp += sizeof(u_short);
+ __putshort(qclass, (u_char *)cp);
+ cp += sizeof(u_short);
+
+ // get the answer
+ for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+ {
+ if ((ptr->Flags).S.Section == DNSREC_ANSWER ||
+ (type == DNS_TYPE_PTR && (ptr->Flags).S.Section==DNSREC_QUESTION))
+ {
+ i = build_rr(cp, ptr, qclass);
+ cp = cp + i;
+ //strcpy(cp, pDnsRecord->pName);
+ //cp += strlen(pDnsRecord->pName);
+ //cp++;
+
+ n++;
+ }
+ }
+ hp->ancount = htons(n);
+
+ // get the authority
+ for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+ {
+ if ((ptr->Flags).S.Section == DNSREC_AUTHORITY )
+ {
+ i = build_rr(cp, ptr, qclass);
+ cp = cp + i;
+
+ n++;
+ }
+ }
+ hp->nscount = htons(n);
+
+ // get the additional resource
+ for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+ {
+ if ((ptr->Flags).S.Section == DNSREC_ADDITIONAL)
+ {
+ i = build_rr(cp, ptr, qclass);
+ cp = cp + i;
+
+ n++;
+ }
+
+ }
+ hp->arcount = htons(n);
+
+ *anslen = (int)(cp - answer);
+ if (*anslen > retanswerlen)
+ memcpy(retanswer, answer, retanswerlen); // partial copy
+ else
+ memcpy(retanswer, answer, *anslen);
+ DnsRecordListFree(pDnsRecord, freetype);
+ return status;
+}
+
+int
+build_rr(char* p, PDNS_RECORD ptr, int qclass)
+{
+ int i = 0;
+ int n = 0;
+ char* cp = p;
+ char* temp = NULL;
+ unsigned int index = 0;
+
+ i = put_qname(cp, ptr->pName);
+ cp = p + i;
+
+ __putshort(ptr->wType, (u_char *)cp);
+ i += sizeof(u_short);
+ cp = p + i;
+ __putshort(qclass, (u_char *)cp);
+ i += sizeof(u_short);
+ cp = p + i;
+ __putlong(ptr->dwTtl, (u_char*)cp);
+ i += sizeof(u_long);
+ cp = p + i;
+ switch (ptr->wType)
+ {
+ case DNS_TYPE_A:
+ __putshort(sizeof(ptr->Data.A), (u_char*)cp); //RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ memcpy(cp, &(ptr->Data.A), sizeof(ptr->Data.A));
+ i += sizeof(ptr->Data.A);
+ break;
+ case DNS_TYPE_NS:
+ case DNS_TYPE_MD:
+ case DNS_TYPE_MF:
+ case DNS_TYPE_CNAME:
+ case DNS_TYPE_MB:
+ case DNS_TYPE_MG:
+ case DNS_TYPE_MR:
+ case DNS_TYPE_PTR:
+ temp = cp; // hold the spot for RD length
+ i += sizeof(u_short);
+ cp = p+i;
+ n = put_qname(cp, ptr->Data.Ptr.pNameHost);
+ i += n;
+ __putshort(n, (u_char*)temp); //set RDLENGTH
+ break;
+ case DNS_TYPE_TEXT:
+ case DNS_TYPE_HINFO:
+ case DNS_TYPE_ISDN:
+ case DNS_TYPE_X25:
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ n = 0;
+ for (index = 0; index < ptr->Data.Txt.dwStringCount; index++)
+ {
+ *cp = (int)(strlen(ptr->Data.Txt.pStringArray[index]));
+ n += *cp;
+ n++;
+ strcpy(++cp, ptr->Data.Txt.pStringArray[index]);
+ }
+ i += n;
+ __putshort(n,(u_char*)temp); // set RDLENGTH
+ break;
+ case DNS_TYPE_SRV:
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ // priority
+ __putshort(ptr->Data.Srv.wPriority, (u_char*)cp);
+ i += sizeof(u_short);
+ cp = p + i;
+ //weight
+ __putshort(ptr->Data.Srv.wWeight, (u_char*)cp);
+ i += sizeof(u_short);
+ cp = p + i;
+ //port
+ __putshort(ptr->Data.Srv.wPort, (u_char*)cp);
+ i += sizeof(u_short);
+ cp = p + i;
+
+ n = put_qname(cp, ptr->Data.Srv.pNameTarget);
+ i+=n;
+ __putshort((u_short)(n + sizeof(u_short)*3),(u_char*)temp);
+
+ break;
+ case DNS_TYPE_MX:
+ case DNS_TYPE_AFSDB:
+ case DNS_TYPE_RT:
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ __putshort(ptr->Data.Mx.wPreference, (u_char*)cp); // put wPreference
+ i += sizeof(u_short);
+ cp = p + i;
+ n = put_qname(cp, ptr->Data.Mx.pNameExchange);
+ i+=n;
+ __putshort((u_short)(n+sizeof(u_short)),(u_char*)temp);
+ break;
+ case DNS_TYPE_SOA:
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ // primary server name
+ n = put_qname(cp, ptr->Data.Soa.pNamePrimaryServer);
+ i+= n;
+ cp = p + i;
+ //the person responsible for this zone.
+ n += put_qname(cp, ptr->Data.Soa.pNameAdministrator);
+ i += n;
+ cp = p + i;
+ //SERIAL
+ __putlong(ptr->Data.Soa.dwSerialNo, cp);
+ n += sizeof(u_long);
+ i += sizeof(u_long);
+ cp = p + i;
+ //refresh
+ __putlong(ptr->Data.Soa.dwRefresh, cp);
+ n += sizeof(u_long);
+ i += sizeof(u_long);
+ cp = p + i;
+ //retry
+ __putlong(ptr->Data.Soa.dwRetry, cp);
+ n += sizeof(u_long);
+ i += sizeof(u_long);
+ cp = p + i;
+ // expire
+ __putlong(ptr->Data.Soa.dwExpire, cp);
+ n += sizeof(u_long);
+ i += sizeof(u_long);
+ cp = p + i;
+ // minimum TTL
+ __putlong(ptr->Data.Soa.dwDefaultTtl, cp);
+ n += sizeof(u_long);
+ i += sizeof(u_long);
+ // set RDLength
+ __putshort(n,(u_char*)temp);
+ break;
+ case DNS_TYPE_NULL:
+ __putshort((short)ptr->Data.Null.dwByteCount, (u_char*)cp); //RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ memcpy(cp, ptr->Data.Null.Data, ptr->Data.Null.dwByteCount);
+ i += ptr->Data.Null.dwByteCount;
+ break;
+ case DNS_TYPE_WKS: // needs more work
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ // address
+ memcpy(cp, &(ptr->Data.Wks.IpAddress), sizeof(ptr->Data.Wks.IpAddress));
+ n = sizeof(ptr->Data.Wks.IpAddress);
+ i += sizeof(ptr->Data.Wks.IpAddress);
+ cp = p + i;
+ // protocol
+ *cp = ptr->Data.Wks.chProtocol;
+ i++;
+ n++;
+ cp = p + i;
+ //bit mask
+ memcpy(cp, &(ptr->Data.Wks.BitMask), sizeof(ptr->Data.Wks.BitMask));
+ n+=sizeof(ptr->Data.Wks.BitMask);
+ i += n;
+ // set RDLength
+ __putshort(n,(u_char*)temp);
+ break;
+ case DNS_TYPE_MINFO:
+ case DNS_TYPE_RP:
+ temp = cp; // hold the spot for RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ // pNameMailbox
+ n = put_qname(cp, ptr->Data.Minfo.pNameMailbox);
+ i+= n;
+ cp = p + i;
+ // pNameErrorsMailbox;
+ n += put_qname(cp, ptr->Data.Minfo.pNameMailbox);
+ i += n;
+ // set RDLength
+ __putshort(n,(u_char*)temp);
+ break;
+ case DNS_TYPE_AAAA:
+ __putshort(sizeof(ptr->Data.AAAA), (u_char*)cp); //RDLENGTH
+ i += sizeof(u_short);
+ cp = p + i;
+ memcpy(cp, &(ptr->Data.AAAA), sizeof(ptr->Data.AAAA));
+ i += sizeof(ptr->Data.AAAA);
+
+ break;
+ }
+ return i;
+}
+
+
+int
+__hostalias(register const char *name, char* abuf)
+{
+ register char *C1, *C2;
+ FILE *fp;
+ char *file;
+// char *getenv(), *strcpy(), *strncpy(); // pbh XXX 11/1/96
+ char buf[BUFSIZ];
+
+
+ file = getenv("HOSTALIASES");
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+ return -1;
+ buf[sizeof(buf) - 1] = '\0';
+ while (fgets(buf, sizeof(buf), fp)) {
+ for (C1 = buf; *C1 && !isspace(*C1); ++C1);
+ if (!*C1)
+ break;
+ *C1 = '\0';
+ if (!strcasecmp(buf, name)) {
+ while (isspace(*++C1));
+ if (!*C1)
+ break;
+ for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
+ abuf[sizeof(abuf) - 1] = *C2 = '\0';
+ (void)strncpy(abuf, C1, sizeof(abuf) - 1);
+ fclose(fp);
+ return 0;
+ }
+ }
+ fclose(fp);
+ return -1;
+}
+
+int WINAPI
+res_mkquery(int op, const char *dname,
+ int qclass, int type,
+ const char *data, int datalen,
+ const struct rrec *newrr,
+ char *buf, int buflen)
+{
+ return -1;
+}
+
+int WINAPI
+res_querydomain(const char *name,
+ const char *domain,
+ int qclass, int type,
+ u_char *answer, int anslen)
+{
+ return -1;
+}
+
+int WINAPI
+res_send(const char *msg, int msglen,
+ char *answer, int anslen)
+{
+ return -1;
+}
+
+int WINAPI
+res_query(char *name, int qclass, int type, u_char *answer, int anslen)
+{
+ return -1;
+}