11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 1998 Massachusetts Institute of Technology 41cb0ef41Sopenharmony_ci * Copyright (c) The c-ares project and its contributors 51cb0ef41Sopenharmony_ci * 61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 71cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 81cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 91cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 101cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 111cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 141cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 151cb0ef41Sopenharmony_ci * Software. 161cb0ef41Sopenharmony_ci * 171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 181cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 191cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 201cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 211cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 221cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 231cb0ef41Sopenharmony_ci * SOFTWARE. 241cb0ef41Sopenharmony_ci * 251cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 261cb0ef41Sopenharmony_ci */ 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#include "ares_setup.h" 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 311cb0ef41Sopenharmony_ci# include <netinet/in.h> 321cb0ef41Sopenharmony_ci#endif 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci#include "ares_nameser.h" 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci#include "ares.h" 371cb0ef41Sopenharmony_ci#include "ares_dns.h" 381cb0ef41Sopenharmony_ci#include "ares_private.h" 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cistatic unsigned short generate_unique_qid(ares_channel_t *channel) 411cb0ef41Sopenharmony_ci{ 421cb0ef41Sopenharmony_ci unsigned short id; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci do { 451cb0ef41Sopenharmony_ci id = ares__generate_new_id(channel->rand_state); 461cb0ef41Sopenharmony_ci } while (ares__htable_szvp_get(channel->queries_by_qid, id, NULL)); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci return id; 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ciares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, 521cb0ef41Sopenharmony_ci size_t qlen, ares_callback callback, void *arg, 531cb0ef41Sopenharmony_ci unsigned short *qid) 541cb0ef41Sopenharmony_ci{ 551cb0ef41Sopenharmony_ci struct query *query; 561cb0ef41Sopenharmony_ci size_t packetsz; 571cb0ef41Sopenharmony_ci struct timeval now = ares__tvnow(); 581cb0ef41Sopenharmony_ci ares_status_t status; 591cb0ef41Sopenharmony_ci unsigned short id = generate_unique_qid(channel); 601cb0ef41Sopenharmony_ci unsigned char *abuf = NULL; 611cb0ef41Sopenharmony_ci size_t alen = 0; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci /* Verify that the query is at least long enough to hold the header. */ 641cb0ef41Sopenharmony_ci if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { 651cb0ef41Sopenharmony_ci callback(arg, ARES_EBADQUERY, 0, NULL, 0); 661cb0ef41Sopenharmony_ci return ARES_EBADQUERY; 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci if (ares__slist_len(channel->servers) == 0) { 691cb0ef41Sopenharmony_ci callback(arg, ARES_ENOSERVER, 0, NULL, 0); 701cb0ef41Sopenharmony_ci return ARES_ENOSERVER; 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci /* Check query cache */ 741cb0ef41Sopenharmony_ci status = ares_qcache_fetch(channel, &now, qbuf, qlen, &abuf, &alen); 751cb0ef41Sopenharmony_ci if (status != ARES_ENOTFOUND) { 761cb0ef41Sopenharmony_ci /* ARES_SUCCESS means we retrieved the cache, anything else is a critical 771cb0ef41Sopenharmony_ci * failure, all result in termination */ 781cb0ef41Sopenharmony_ci callback(arg, (int)status, 0, abuf, (int)alen); 791cb0ef41Sopenharmony_ci ares_free(abuf); 801cb0ef41Sopenharmony_ci return status; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci /* Allocate space for query and allocated fields. */ 841cb0ef41Sopenharmony_ci query = ares_malloc(sizeof(struct query)); 851cb0ef41Sopenharmony_ci if (!query) { 861cb0ef41Sopenharmony_ci callback(arg, ARES_ENOMEM, 0, NULL, 0); 871cb0ef41Sopenharmony_ci return ARES_ENOMEM; 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci memset(query, 0, sizeof(*query)); 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci query->channel = channel; 921cb0ef41Sopenharmony_ci query->qbuf = ares_malloc(qlen); 931cb0ef41Sopenharmony_ci if (!query->qbuf) { 941cb0ef41Sopenharmony_ci ares_free(query); 951cb0ef41Sopenharmony_ci callback(arg, ARES_ENOMEM, 0, NULL, 0); 961cb0ef41Sopenharmony_ci return ARES_ENOMEM; 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci query->qid = id; 1001cb0ef41Sopenharmony_ci query->timeout.tv_sec = 0; 1011cb0ef41Sopenharmony_ci query->timeout.tv_usec = 0; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci /* Ignore first 2 bytes, assign our own query id */ 1041cb0ef41Sopenharmony_ci query->qbuf[0] = (unsigned char)((id >> 8) & 0xFF); 1051cb0ef41Sopenharmony_ci query->qbuf[1] = (unsigned char)(id & 0xFF); 1061cb0ef41Sopenharmony_ci memcpy(query->qbuf + 2, qbuf + 2, qlen - 2); 1071cb0ef41Sopenharmony_ci query->qlen = qlen; 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci /* Fill in query arguments. */ 1101cb0ef41Sopenharmony_ci query->callback = callback; 1111cb0ef41Sopenharmony_ci query->arg = arg; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci /* Initialize query status. */ 1141cb0ef41Sopenharmony_ci query->try_count = 0; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci packetsz = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : PACKETSZ; 1171cb0ef41Sopenharmony_ci query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > packetsz; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci query->error_status = ARES_SUCCESS; 1201cb0ef41Sopenharmony_ci query->timeouts = 0; 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci /* Initialize our list nodes. */ 1231cb0ef41Sopenharmony_ci query->node_queries_by_timeout = NULL; 1241cb0ef41Sopenharmony_ci query->node_queries_to_conn = NULL; 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci /* Chain the query into the list of all queries. */ 1271cb0ef41Sopenharmony_ci query->node_all_queries = 1281cb0ef41Sopenharmony_ci ares__llist_insert_last(channel->all_queries, query); 1291cb0ef41Sopenharmony_ci if (query->node_all_queries == NULL) { 1301cb0ef41Sopenharmony_ci callback(arg, ARES_ENOMEM, 0, NULL, 0); 1311cb0ef41Sopenharmony_ci ares__free_query(query); 1321cb0ef41Sopenharmony_ci return ARES_ENOMEM; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci /* Keep track of queries bucketed by qid, so we can process DNS 1361cb0ef41Sopenharmony_ci * responses quickly. 1371cb0ef41Sopenharmony_ci */ 1381cb0ef41Sopenharmony_ci if (!ares__htable_szvp_insert(channel->queries_by_qid, query->qid, query)) { 1391cb0ef41Sopenharmony_ci callback(arg, ARES_ENOMEM, 0, NULL, 0); 1401cb0ef41Sopenharmony_ci ares__free_query(query); 1411cb0ef41Sopenharmony_ci return ARES_ENOMEM; 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci /* Perform the first query action. */ 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci status = ares__send_query(query, &now); 1471cb0ef41Sopenharmony_ci if (status == ARES_SUCCESS && qid) { 1481cb0ef41Sopenharmony_ci *qid = id; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci return status; 1511cb0ef41Sopenharmony_ci} 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_civoid ares_send(ares_channel_t *channel, const unsigned char *qbuf, int qlen, 1541cb0ef41Sopenharmony_ci ares_callback callback, void *arg) 1551cb0ef41Sopenharmony_ci{ 1561cb0ef41Sopenharmony_ci if (channel == NULL) { 1571cb0ef41Sopenharmony_ci return; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci ares__channel_lock(channel); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci ares_send_ex(channel, qbuf, (size_t)qlen, callback, arg, NULL); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci ares__channel_unlock(channel); 1651cb0ef41Sopenharmony_ci} 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_cisize_t ares_queue_active_queries(ares_channel_t *channel) 1681cb0ef41Sopenharmony_ci{ 1691cb0ef41Sopenharmony_ci size_t len; 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci if (channel == NULL) { 1721cb0ef41Sopenharmony_ci return 0; 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci ares__channel_lock(channel); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci len = ares__llist_len(channel->all_queries); 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci ares__channel_unlock(channel); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci return len; 1821cb0ef41Sopenharmony_ci} 183