• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) 1998 Massachusetts Institute of Technology
4  * Copyright (c) The c-ares project and its contributors
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * SPDX-License-Identifier: MIT
26  */
27 
28 #include "ares_private.h"
29 
30 #ifdef HAVE_NETINET_IN_H
31 #  include <netinet/in.h>
32 #endif
33 
34 typedef struct {
35   ares_callback_dnsrec callback;
36   void                *arg;
37 } ares_query_dnsrec_arg_t;
38 
ares_query_dnsrec_cb(void * arg,ares_status_t status,size_t timeouts,const ares_dns_record_t * dnsrec)39 static void ares_query_dnsrec_cb(void *arg, ares_status_t status,
40                                  size_t                   timeouts,
41                                  const ares_dns_record_t *dnsrec)
42 {
43   ares_query_dnsrec_arg_t *qquery = arg;
44 
45   if (status != ARES_SUCCESS) {
46     qquery->callback(qquery->arg, status, timeouts, dnsrec);
47   } else {
48     size_t           ancount;
49     ares_dns_rcode_t rcode;
50     /* Pull the response code and answer count from the packet and convert any
51      * errors.
52      */
53     rcode   = ares_dns_record_get_rcode(dnsrec);
54     ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
55     status  = ares_dns_query_reply_tostatus(rcode, ancount);
56     qquery->callback(qquery->arg, status, timeouts, dnsrec);
57   }
58   ares_free(qquery);
59 }
60 
ares_query_nolock(ares_channel_t * channel,const char * name,ares_dns_class_t dnsclass,ares_dns_rec_type_t type,ares_callback_dnsrec callback,void * arg,unsigned short * qid)61 ares_status_t ares_query_nolock(ares_channel_t *channel, const char *name,
62                                 ares_dns_class_t     dnsclass,
63                                 ares_dns_rec_type_t  type,
64                                 ares_callback_dnsrec callback, void *arg,
65                                 unsigned short *qid)
66 {
67   ares_status_t            status;
68   ares_dns_record_t       *dnsrec = NULL;
69   ares_dns_flags_t         flags  = 0;
70   ares_query_dnsrec_arg_t *qquery = NULL;
71 
72   if (channel == NULL || name == NULL || callback == NULL) {
73     /* LCOV_EXCL_START: DefensiveCoding */
74     status = ARES_EFORMERR;
75     if (callback != NULL) {
76       callback(arg, status, 0, NULL);
77     }
78     return status;
79     /* LCOV_EXCL_STOP */
80   }
81 
82   if (!(channel->flags & ARES_FLAG_NORECURSE)) {
83     flags |= ARES_FLAG_RD;
84   }
85 
86   status = ares_dns_record_create_query(
87     &dnsrec, name, dnsclass, type, 0, flags,
88     (size_t)(channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0);
89   if (status != ARES_SUCCESS) {
90     callback(arg, status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
91     return status;                  /* LCOV_EXCL_LINE: OutOfMemory */
92   }
93 
94   qquery = ares_malloc(sizeof(*qquery));
95   if (qquery == NULL) {
96     /* LCOV_EXCL_START: OutOfMemory */
97     status = ARES_ENOMEM;
98     callback(arg, status, 0, NULL);
99     ares_dns_record_destroy(dnsrec);
100     return status;
101     /* LCOV_EXCL_STOP */
102   }
103 
104   qquery->callback = callback;
105   qquery->arg      = arg;
106 
107   /* Send it off.  qcallback will be called when we get an answer. */
108   status = ares_send_nolock(channel, NULL, 0, dnsrec, ares_query_dnsrec_cb,
109                             qquery, qid);
110 
111   ares_dns_record_destroy(dnsrec);
112   return status;
113 }
114 
ares_query_dnsrec(ares_channel_t * channel,const char * name,ares_dns_class_t dnsclass,ares_dns_rec_type_t type,ares_callback_dnsrec callback,void * arg,unsigned short * qid)115 ares_status_t ares_query_dnsrec(ares_channel_t *channel, const char *name,
116                                 ares_dns_class_t     dnsclass,
117                                 ares_dns_rec_type_t  type,
118                                 ares_callback_dnsrec callback, void *arg,
119                                 unsigned short *qid)
120 {
121   ares_status_t status;
122 
123   if (channel == NULL) {
124     return ARES_EFORMERR;
125   }
126 
127   ares_channel_lock(channel);
128   status = ares_query_nolock(channel, name, dnsclass, type, callback, arg, qid);
129   ares_channel_unlock(channel);
130   return status;
131 }
132 
ares_query(ares_channel_t * channel,const char * name,int dnsclass,int type,ares_callback callback,void * arg)133 void ares_query(ares_channel_t *channel, const char *name, int dnsclass,
134                 int type, ares_callback callback, void *arg)
135 {
136   void *carg = NULL;
137 
138   if (channel == NULL) {
139     return;
140   }
141 
142   carg = ares_dnsrec_convert_arg(callback, arg);
143   if (carg == NULL) {
144     callback(arg, ARES_ENOMEM, 0, NULL, 0); /* LCOV_EXCL_LINE: OutOfMemory */
145     return;                                 /* LCOV_EXCL_LINE: OutOfMemory */
146   }
147 
148   ares_query_dnsrec(channel, name, (ares_dns_class_t)dnsclass,
149                     (ares_dns_rec_type_t)type, ares_dnsrec_convert_cb, carg,
150                     NULL);
151 }
152