6
* @module res_quer.c | Contains the implementation of res_query,
7
* res_search, and res_querydomain
9
* WSHelper DNS/Hesiod Library for WINSOCK
14
* Copyright (c) 1988 Regents of the University of California.
15
* All rights reserved.
17
* Redistribution and use in source and binary forms, with or without
18
* modification, are permitted provided that the following conditions
20
* 1. Redistributions of source code must retain the above copyright
21
* notice, this list of conditions and the following disclaimer.
22
* 2. Redistributions in binary form must reproduce the above copyright
23
* notice, this list of conditions and the following disclaimer in the
24
* documentation and/or other materials provided with the distribution.
25
* 3. All advertising materials mentioning features or use of this software
26
* must display the following acknowledgement:
27
* This product includes software developed by the University of
28
* California, Berkeley and its contributors.
29
* 4. Neither the name of the University nor the names of its contributors
30
* may be used to endorse or promote products derived from this software
31
* without specific prior written permission.
33
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46
#if defined(LIBC_SCCS) && !defined(lint)
47
static char sccsid[] = "@(#)res_query.c 5.11 (Berkeley) 3/6/91";
48
#endif /* LIBC_SCCS and not lint */
59
#define MAX_MSG_SIZE 0x8000
61
#define strcasecmp stricmp
67
__hostalias(register const char *name, char* abuf);
68
DNS_STATUS do_res_search(const char *name, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen);
69
void __putshort(register u_short, register u_char *);
70
void __putlong(register u_long, u_char *);
71
int build_rr(char* p, PDNS_RECORD ptr, int qclass);
72
int put_qname(char* p, char* qname);
77
a generic query interface to the DNS name space. The query is performed with the dnsapi and
78
the answer buffer is populated based on the returned RR set.
80
\param[in] name domain name
81
\param[in] qclass class of query(such as DNS_CLASS_INTERNET, DNS_CLASS_CSNET, DNS_CLASS_CHAOS,
82
DNS_CLASS_HESIOD. Defined in windns.h)
83
\param[in] type type of query(such as DNS_TYPE_A, DNS_TYPE_NS, DNS_TYPE_MX, DNS_TYPE_SRV. Defined in
85
\param[in] answer buffer to put answer in
86
\param[in] anslen size of the answer buffer. compare the anslen with the return value, if the return
87
value is bigger than anslen, it means the answer buffer doesn't contain the complete
88
response. You will need to call this function again with a bigger answer buffer if
89
you care about the complete response
91
\retval return the size of the response on success, -1 on error
96
res_search(const char *name, int qclass, int type, u_char *answer, int anslen)
97
/* domain name, class and type of query, buffer to put answer, size of answer */
102
char queryname[DNS_MAX_NAME_BUFFER_LENGTH ];
103
register const char *cp;
109
memset(answer, 0, anslen);
110
memset(queryname, 0, sizeof(queryname));
112
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
115
for (cp = name, n = 0; *cp; cp++)
119
if (n == 0 && !__hostalias(name, queryname) && strlen(queryname)>0)
121
status = do_res_search(queryname, qclass, type, answer, anslen, &len);
126
if ((n == 0 && _res.options & RES_DEFNAMES))
127
// (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
129
for (domain = _res.dnsrch; *domain; domain++) {
130
strcpy(queryname, name);
131
strcat(queryname, ".");
132
strcat(queryname, *domain);
133
status = do_res_search(queryname, qclass, type, answer, anslen, &len);
140
strcpy(queryname, name);
141
status = do_res_search(queryname, qclass, type, answer, anslen, &len);
147
if (_res.options & RES_DEBUG)
149
wsprintf(debstr, "res_query failed\n");
150
OutputDebugString(debstr);
159
put_qname(char* cp, char* qname)
166
while (p = strchr(temp, '.'))
177
strncpy(cp, temp, n);
197
do_res_search(const char *queryname, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen)
199
PDNS_RECORD pDnsRecord;
202
DNS_FREE_TYPE freetype ;
207
u_char answer[MAX_MSG_SIZE];
208
DWORD options = DNS_QUERY_STANDARD;
209
freetype = DnsFreeRecordListDeep;
211
memset(answer, 0, MAX_MSG_SIZE);
212
if (!(_res.options & RES_RECURSE))
213
options = options | DNS_QUERY_NO_RECURSION;
214
if (_res.options & RES_USEVC)
215
options = options | DNS_QUERY_USE_TCP_ONLY;
216
if (_res.options & RES_IGNTC)
217
options = options | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE;
219
status = DnsQuery_A(queryname, //pointer to OwnerName
220
type, //Type of the record to be queried
222
NULL, //contains DNS server IP address
223
&pDnsRecord, //Resource record comprising the response
224
NULL); //reserved for future use
230
hp = (HEADER *) answer;
231
cp = answer + sizeof(HEADER);
233
// populating the header
234
hp->id = htons(++_res.id); // query id
235
hp->qr = 1; // 0 for query 1 for response
236
hp->opcode = 0; // standard query
237
hp->aa = 1; // authoritative answer
238
hp->tc = 0; // no truncation
239
hp->rd = (_res.options & RES_RECURSE) != 0; // resursion desired
240
hp->ra = 1; // recursion available
241
hp->pr = (_res.options & RES_PRIMARY) != 0; // primary server required
243
hp->qdcount = htons(1); // number of question entries
244
i = put_qname(cp, (char*)queryname);
246
__putshort(type, (u_char *)cp);
247
cp += sizeof(u_short);
248
__putshort(qclass, (u_char *)cp);
249
cp += sizeof(u_short);
252
for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
254
if ((ptr->Flags).S.Section == DNSREC_ANSWER ||
255
(type == DNS_TYPE_PTR && (ptr->Flags).S.Section==DNSREC_QUESTION))
257
i = build_rr(cp, ptr, qclass);
259
//strcpy(cp, pDnsRecord->pName);
260
//cp += strlen(pDnsRecord->pName);
266
hp->ancount = htons(n);
269
for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
271
if ((ptr->Flags).S.Section == DNSREC_AUTHORITY )
273
i = build_rr(cp, ptr, qclass);
279
hp->nscount = htons(n);
281
// get the additional resource
282
for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
284
if ((ptr->Flags).S.Section == DNSREC_ADDITIONAL)
286
i = build_rr(cp, ptr, qclass);
293
hp->arcount = htons(n);
295
*anslen = (int)(cp - answer);
296
if (*anslen > retanswerlen)
297
memcpy(retanswer, answer, retanswerlen); // partial copy
299
memcpy(retanswer, answer, *anslen);
300
DnsRecordListFree(pDnsRecord, freetype);
305
build_rr(char* p, PDNS_RECORD ptr, int qclass)
311
unsigned int index = 0;
313
i = put_qname(cp, ptr->pName);
316
__putshort(ptr->wType, (u_char *)cp);
317
i += sizeof(u_short);
319
__putshort(qclass, (u_char *)cp);
320
i += sizeof(u_short);
322
__putlong(ptr->dwTtl, (u_char*)cp);
328
__putshort(sizeof(ptr->Data.A), (u_char*)cp); //RDLENGTH
329
i += sizeof(u_short);
331
memcpy(cp, &(ptr->Data.A), sizeof(ptr->Data.A));
332
i += sizeof(ptr->Data.A);
342
temp = cp; // hold the spot for RD length
343
i += sizeof(u_short);
345
n = put_qname(cp, ptr->Data.Ptr.pNameHost);
347
__putshort(n, (u_char*)temp); //set RDLENGTH
353
temp = cp; // hold the spot for RDLENGTH
354
i += sizeof(u_short);
357
for (index = 0; index < ptr->Data.Txt.dwStringCount; index++)
359
*cp = (int)(strlen(ptr->Data.Txt.pStringArray[index]));
362
strcpy(++cp, ptr->Data.Txt.pStringArray[index]);
365
__putshort(n,(u_char*)temp); // set RDLENGTH
368
temp = cp; // hold the spot for RDLENGTH
369
i += sizeof(u_short);
372
__putshort(ptr->Data.Srv.wPriority, (u_char*)cp);
373
i += sizeof(u_short);
376
__putshort(ptr->Data.Srv.wWeight, (u_char*)cp);
377
i += sizeof(u_short);
380
__putshort(ptr->Data.Srv.wPort, (u_char*)cp);
381
i += sizeof(u_short);
384
n = put_qname(cp, ptr->Data.Srv.pNameTarget);
386
__putshort((u_short)(n + sizeof(u_short)*3),(u_char*)temp);
392
temp = cp; // hold the spot for RDLENGTH
393
i += sizeof(u_short);
395
__putshort(ptr->Data.Mx.wPreference, (u_char*)cp); // put wPreference
396
i += sizeof(u_short);
398
n = put_qname(cp, ptr->Data.Mx.pNameExchange);
400
__putshort((u_short)(n+sizeof(u_short)),(u_char*)temp);
403
temp = cp; // hold the spot for RDLENGTH
404
i += sizeof(u_short);
406
// primary server name
407
n = put_qname(cp, ptr->Data.Soa.pNamePrimaryServer);
410
//the person responsible for this zone.
411
n += put_qname(cp, ptr->Data.Soa.pNameAdministrator);
415
__putlong(ptr->Data.Soa.dwSerialNo, cp);
420
__putlong(ptr->Data.Soa.dwRefresh, cp);
425
__putlong(ptr->Data.Soa.dwRetry, cp);
430
__putlong(ptr->Data.Soa.dwExpire, cp);
435
__putlong(ptr->Data.Soa.dwDefaultTtl, cp);
439
__putshort(n,(u_char*)temp);
442
__putshort((short)ptr->Data.Null.dwByteCount, (u_char*)cp); //RDLENGTH
443
i += sizeof(u_short);
445
memcpy(cp, ptr->Data.Null.Data, ptr->Data.Null.dwByteCount);
446
i += ptr->Data.Null.dwByteCount;
448
case DNS_TYPE_WKS: // needs more work
449
temp = cp; // hold the spot for RDLENGTH
450
i += sizeof(u_short);
453
memcpy(cp, &(ptr->Data.Wks.IpAddress), sizeof(ptr->Data.Wks.IpAddress));
454
n = sizeof(ptr->Data.Wks.IpAddress);
455
i += sizeof(ptr->Data.Wks.IpAddress);
458
*cp = ptr->Data.Wks.chProtocol;
463
memcpy(cp, &(ptr->Data.Wks.BitMask), sizeof(ptr->Data.Wks.BitMask));
464
n+=sizeof(ptr->Data.Wks.BitMask);
467
__putshort(n,(u_char*)temp);
471
temp = cp; // hold the spot for RDLENGTH
472
i += sizeof(u_short);
475
n = put_qname(cp, ptr->Data.Minfo.pNameMailbox);
478
// pNameErrorsMailbox;
479
n += put_qname(cp, ptr->Data.Minfo.pNameMailbox);
482
__putshort(n,(u_char*)temp);
485
__putshort(sizeof(ptr->Data.AAAA), (u_char*)cp); //RDLENGTH
486
i += sizeof(u_short);
488
memcpy(cp, &(ptr->Data.AAAA), sizeof(ptr->Data.AAAA));
489
i += sizeof(ptr->Data.AAAA);
498
__hostalias(register const char *name, char* abuf)
500
register char *C1, *C2;
503
// char *getenv(), *strcpy(), *strncpy(); // pbh XXX 11/1/96
507
file = getenv("HOSTALIASES");
508
if (file == NULL || (fp = fopen(file, "r")) == NULL)
510
buf[sizeof(buf) - 1] = '\0';
511
while (fgets(buf, sizeof(buf), fp)) {
512
for (C1 = buf; *C1 && !isspace(*C1); ++C1);
516
if (!strcasecmp(buf, name)) {
517
while (isspace(*++C1));
520
for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
521
abuf[sizeof(abuf) - 1] = *C2 = '\0';
522
(void)strncpy(abuf, C1, sizeof(abuf) - 1);
532
res_mkquery(int op, const char *dname,
533
int qclass, int type,
534
const char *data, int datalen,
535
const struct rrec *newrr,
536
char *buf, int buflen)
542
res_querydomain(const char *name,
544
int qclass, int type,
545
u_char *answer, int anslen)
551
res_send(const char *msg, int msglen,
552
char *answer, int anslen)
558
res_query(char *name, int qclass, int type, u_char *answer, int anslen)