ares_parse_a_reply.c (3063B)
1 /* MIT License 2 * 3 * Copyright (c) 1998 Massachusetts Institute of Technology 4 * Copyright (c) 2019 Andrew Selivanov 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 #ifdef HAVE_NETDB_H 34 # include <netdb.h> 35 #endif 36 #ifdef HAVE_ARPA_INET_H 37 # include <arpa/inet.h> 38 #endif 39 40 #ifdef HAVE_STRINGS_H 41 # include <strings.h> 42 #endif 43 44 #ifdef HAVE_LIMITS_H 45 # include <limits.h> 46 #endif 47 48 int ares_parse_a_reply(const unsigned char *abuf, int alen, 49 struct hostent **host, struct ares_addrttl *addrttls, 50 int *naddrttls) 51 { 52 struct ares_addrinfo ai; 53 char *question_hostname = NULL; 54 ares_status_t status; 55 size_t req_naddrttls = 0; 56 ares_dns_record_t *dnsrec = NULL; 57 58 if (alen < 0) { 59 return ARES_EBADRESP; 60 } 61 62 if (naddrttls) { 63 req_naddrttls = (size_t)*naddrttls; 64 *naddrttls = 0; 65 } 66 67 memset(&ai, 0, sizeof(ai)); 68 69 status = ares_dns_parse(abuf, (size_t)alen, 0, &dnsrec); 70 if (status != ARES_SUCCESS) { 71 goto fail; 72 } 73 74 status = ares_parse_into_addrinfo(dnsrec, 0, 0, &ai); 75 if (status != ARES_SUCCESS && status != ARES_ENODATA) { 76 goto fail; 77 } 78 79 if (host != NULL) { 80 *host = NULL; 81 status = ares_addrinfo2hostent(&ai, AF_INET, host); 82 if (status != ARES_SUCCESS && status != ARES_ENODATA) { 83 goto fail; /* LCOV_EXCL_LINE: DefensiveCoding */ 84 } 85 } 86 87 if (addrttls != NULL && req_naddrttls) { 88 size_t temp_naddrttls = 0; 89 ares_addrinfo2addrttl(&ai, AF_INET, req_naddrttls, addrttls, NULL, 90 &temp_naddrttls); 91 *naddrttls = (int)temp_naddrttls; 92 } 93 94 95 fail: 96 ares_freeaddrinfo_cnames(ai.cnames); 97 ares_freeaddrinfo_nodes(ai.nodes); 98 ares_free(ai.name); 99 ares_free(question_hostname); 100 ares_dns_record_destroy(dnsrec); 101 102 if (status == ARES_EBADNAME) { 103 status = ARES_EBADRESP; 104 } 105 106 return (int)status; 107 }