OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / libares / ares_query.c
1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2  *
3  * Permission to use, copy, modify, and distribute this
4  * software and its documentation for any purpose and without
5  * fee is hereby granted, provided that the above copyright
6  * notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting
8  * documentation, and that the name of M.I.T. not be used in
9  * advertising or publicity pertaining to distribution of the
10  * software without specific, written prior permission.
11  * M.I.T. makes no representations about the suitability of
12  * this software for any purpose.  It is provided "as is"
13  * without express or implied warranty.
14  */
15
16 static const char rcsid[] = "$Id: ares_query.c,v 1.5 2000/09/21 19:15:58 ghudson Exp $";
17
18 #include <sys/types.h>
19 #include <netinet/in.h>
20 #include <arpa/nameser.h>
21 #include <stdlib.h>
22 #include "ares.h"
23 #include "ares_dns.h"
24 #include "ares_private.h"
25
26 struct qquery {
27   ares_callback callback;
28   void *arg;
29 };
30
31 static void qcallback(void *arg, int status, unsigned char *abuf, int alen);
32
33 void ares_query(ares_channel channel, const char *name, int dnsclass,
34                 int type, ares_callback callback, void *arg)
35 {
36   struct qquery *qquery;
37   unsigned char *qbuf;
38   int qlen, rd, status;
39
40   /* Compose the query. */
41   rd = !(channel->flags & ARES_FLAG_NORECURSE);
42   status = ares_mkquery(name, dnsclass, type, channel->next_id, rd, &qbuf,
43                         &qlen);
44   channel->next_id++;
45   if (status != ARES_SUCCESS)
46     {
47       callback(arg, status, NULL, 0);
48       return;
49     }
50
51   /* Allocate and fill in the query structure. */
52   qquery = malloc(sizeof(struct qquery));
53   if (!qquery)
54     {
55       ares_free_string(qbuf);
56       callback(arg, ARES_ENOMEM, NULL, 0);
57       return;
58     }
59   qquery->callback = callback;
60   qquery->arg = arg;
61
62   /* Send it off.  qcallback will be called when we get an answer. */
63   ares_send(channel, qbuf, qlen, qcallback, qquery);
64   ares_free_string(qbuf);
65 }
66
67 static void qcallback(void *arg, int status, unsigned char *abuf, int alen)
68 {
69   struct qquery *qquery = (struct qquery *) arg;
70   unsigned int ancount;
71   int rcode;
72
73   if (status != ARES_SUCCESS)
74     qquery->callback(qquery->arg, status, abuf, alen);
75   else
76     {
77       /* Pull the response code and answer count from the packet. */
78       rcode = DNS_HEADER_RCODE(abuf);
79       ancount = DNS_HEADER_ANCOUNT(abuf);
80
81       /* Convert errors. */
82       switch (rcode)
83         {
84         case NOERROR:
85           status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA;
86           break;
87         case FORMERR:
88           status = ARES_EFORMERR;
89           break;
90         case SERVFAIL:
91           status = ARES_ESERVFAIL;
92           break;
93         case NXDOMAIN:
94           status = ARES_ENOTFOUND;
95           break;
96         case NOTIMP:
97           status = ARES_ENOTIMP;
98           break;
99         case REFUSED:
100           status = ARES_EREFUSED;
101           break;
102         }
103       qquery->callback(qquery->arg, status, abuf, alen);
104     }
105   free(qquery);
106 }