aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-07-30 09:57:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-07-30 10:08:52 +0300
commit5b405616d0467647cb365e71237976a9f3810b42 (patch)
treec35e742877f95ba2b9357f178197c755f121cb1a /contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
parent997c68115bc1c9dd2fce5a6a6f8eae92ad628df7 (diff)
downloadydb-5b405616d0467647cb365e71237976a9f3810b42.tar.gz
Update contrib/libs/c-ares to 1.28.1
db71d0a3bd9ec3cf1e1ccb5a9cfac8abfd43fdb7
Diffstat (limited to 'contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c')
-rw-r--r--contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c200
1 files changed, 69 insertions, 131 deletions
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c b/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
index 0125092c02..f27bcce733 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
+++ b/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
@@ -1,7 +1,6 @@
/* MIT License
*
- * Copyright (c) 1998 Massachusetts Institute of Technology
- * Copyright (c) 2009 Jakub Hrozek
+ * Copyright (c) 2023 Brad House
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,153 +25,92 @@
*/
#include "ares_setup.h"
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-
-#include "ares_nameser.h"
-
#include "ares.h"
-#include "ares_dns.h"
#include "ares_data.h"
#include "ares_private.h"
-int
-ares_parse_srv_reply (const unsigned char *abuf, int alen,
- struct ares_srv_reply **srv_out)
+int ares_parse_srv_reply(const unsigned char *abuf, int alen_int,
+ struct ares_srv_reply **srv_out)
{
- unsigned int qdcount, ancount, i;
- const unsigned char *aptr, *vptr;
- int status, rr_type, rr_class, rr_len;
- long len;
- char *hostname = NULL, *rr_name = NULL;
+ ares_status_t status;
+ size_t alen;
struct ares_srv_reply *srv_head = NULL;
struct ares_srv_reply *srv_last = NULL;
struct ares_srv_reply *srv_curr;
+ ares_dns_record_t *dnsrec = NULL;
+ size_t i;
- /* Set *srv_out to NULL for all failure cases. */
*srv_out = NULL;
- /* Give up if abuf doesn't have room for a header. */
- if (alen < HFIXEDSZ)
+ if (alen_int < 0) {
return ARES_EBADRESP;
+ }
- /* Fetch the question and answer count from the header. */
- qdcount = DNS_HEADER_QDCOUNT (abuf);
- ancount = DNS_HEADER_ANCOUNT (abuf);
- if (qdcount != 1)
- return ARES_EBADRESP;
- if (ancount == 0)
- return ARES_ENODATA;
-
- /* Expand the name from the question, and skip past the question. */
- aptr = abuf + HFIXEDSZ;
- status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
- if (status != ARES_SUCCESS)
- return status;
-
- if (aptr + len + QFIXEDSZ > abuf + alen)
- {
- ares_free (hostname);
- return ARES_EBADRESP;
+ alen = (size_t)alen_int;
+
+ status = ares_dns_parse(abuf, alen, 0, &dnsrec);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ if (ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER) == 0) {
+ status = ARES_ENODATA;
+ goto done;
+ }
+
+ for (i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
+ const ares_dns_rr_t *rr =
+ ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i);
+
+ if (rr == NULL) {
+ /* Shouldn't be possible */
+ status = ARES_EBADRESP;
+ goto done;
}
- aptr += len + QFIXEDSZ;
-
- /* Examine each answer resource record (RR) in turn. */
- for (i = 0; i < ancount; i++)
- {
- /* Decode the RR up to the data field. */
- status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
- if (status != ARES_SUCCESS)
- {
- break;
- }
- aptr += len;
- if (aptr + RRFIXEDSZ > abuf + alen)
- {
- status = ARES_EBADRESP;
- break;
- }
- rr_type = DNS_RR_TYPE (aptr);
- rr_class = DNS_RR_CLASS (aptr);
- rr_len = DNS_RR_LEN (aptr);
- aptr += RRFIXEDSZ;
- if (aptr + rr_len > abuf + alen)
- {
- status = ARES_EBADRESP;
- break;
- }
-
- /* Check if we are really looking at a SRV record */
- if (rr_class == C_IN && rr_type == T_SRV)
- {
- /* parse the SRV record itself */
- if (rr_len < 6)
- {
- status = ARES_EBADRESP;
- break;
- }
-
- /* Allocate storage for this SRV answer appending it to the list */
- srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
- if (!srv_curr)
- {
- status = ARES_ENOMEM;
- break;
- }
- if (srv_last)
- {
- srv_last->next = srv_curr;
- }
- else
- {
- srv_head = srv_curr;
- }
- srv_last = srv_curr;
-
- vptr = aptr;
- srv_curr->priority = DNS__16BIT(vptr);
- vptr += sizeof(unsigned short);
- srv_curr->weight = DNS__16BIT(vptr);
- vptr += sizeof(unsigned short);
- srv_curr->port = DNS__16BIT(vptr);
- vptr += sizeof(unsigned short);
-
- status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len);
- if (status != ARES_SUCCESS)
- break;
- }
-
- /* Don't lose memory in the next iteration */
- ares_free (rr_name);
- rr_name = NULL;
-
- /* Move on to the next record */
- aptr += rr_len;
+
+ if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
+ ares_dns_rr_get_type(rr) != ARES_REC_TYPE_SRV) {
+ continue;
}
- if (hostname)
- ares_free (hostname);
- if (rr_name)
- ares_free (rr_name);
+ /* Allocate storage for this SRV answer appending it to the list */
+ srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
+ if (srv_curr == NULL) {
+ status = ARES_ENOMEM;
+ goto done;
+ }
- /* clean up on error */
- if (status != ARES_SUCCESS)
- {
- if (srv_head)
- ares_free_data (srv_head);
- return status;
+ /* Link in the record */
+ if (srv_last) {
+ srv_last->next = srv_curr;
+ } else {
+ srv_head = srv_curr;
}
+ srv_last = srv_curr;
+
+
+ srv_curr->priority = ares_dns_rr_get_u16(rr, ARES_RR_SRV_PRIORITY);
+ srv_curr->weight = ares_dns_rr_get_u16(rr, ARES_RR_SRV_WEIGHT);
+ srv_curr->port = ares_dns_rr_get_u16(rr, ARES_RR_SRV_PORT);
- /* everything looks fine, return the data */
- *srv_out = srv_head;
+ srv_curr->host = ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_SRV_TARGET));
- return ARES_SUCCESS;
+ if (srv_curr->host == NULL) {
+ status = ARES_ENOMEM;
+ goto done;
+ }
+ }
+
+done:
+ /* clean up on error */
+ if (status != ARES_SUCCESS) {
+ if (srv_head) {
+ ares_free_data(srv_head);
+ }
+ } else {
+ /* everything looks fine, return the data */
+ *srv_out = srv_head;
+ }
+ ares_dns_record_destroy(dnsrec);
+ return (int)status;
}