ares_parse_srv_reply.c
Go to the documentation of this file.
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  * Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com>
4  *
5  * Permission to use, copy, modify, and distribute this
6  * software and its documentation for any purpose and without
7  * fee is hereby granted, provided that the above copyright
8  * notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting
10  * documentation, and that the name of M.I.T. not be used in
11  * advertising or publicity pertaining to distribution of the
12  * software without specific, written prior permission.
13  * M.I.T. makes no representations about the suitability of
14  * this software for any purpose. It is provided "as is"
15  * without express or implied warranty.
16  */
17 
18 #include "ares_setup.h"
19 
20 #ifdef HAVE_NETINET_IN_H
21 # include <netinet/in.h>
22 #endif
23 #ifdef HAVE_NETDB_H
24 # include <netdb.h>
25 #endif
26 #ifdef HAVE_ARPA_INET_H
27 # include <arpa/inet.h>
28 #endif
29 
30 #include "ares_nameser.h"
31 
32 #include "ares.h"
33 #include "ares_dns.h"
34 #include "ares_data.h"
35 #include "ares_private.h"
36 
37 int
38 ares_parse_srv_reply (const unsigned char *abuf, int alen,
39  struct ares_srv_reply **srv_out)
40 {
41  unsigned int qdcount, ancount, i;
42  const unsigned char *aptr, *vptr;
43  int status, rr_type, rr_class, rr_len;
44  long len;
45  char *hostname = NULL, *rr_name = NULL;
46  struct ares_srv_reply *srv_head = NULL;
47  struct ares_srv_reply *srv_last = NULL;
48  struct ares_srv_reply *srv_curr;
49 
50  /* Set *srv_out to NULL for all failure cases. */
51  *srv_out = NULL;
52 
53  /* Give up if abuf doesn't have room for a header. */
54  if (alen < HFIXEDSZ)
55  return ARES_EBADRESP;
56 
57  /* Fetch the question and answer count from the header. */
58  qdcount = DNS_HEADER_QDCOUNT (abuf);
59  ancount = DNS_HEADER_ANCOUNT (abuf);
60  if (qdcount != 1)
61  return ARES_EBADRESP;
62  if (ancount == 0)
63  return ARES_ENODATA;
64 
65  /* Expand the name from the question, and skip past the question. */
66  aptr = abuf + HFIXEDSZ;
67  status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
68  if (status != ARES_SUCCESS)
69  return status;
70 
71  if (aptr + len + QFIXEDSZ > abuf + alen)
72  {
73  ares_free (hostname);
74  return ARES_EBADRESP;
75  }
76  aptr += len + QFIXEDSZ;
77 
78  /* Examine each answer resource record (RR) in turn. */
79  for (i = 0; i < ancount; i++)
80  {
81  /* Decode the RR up to the data field. */
82  status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
83  if (status != ARES_SUCCESS)
84  {
85  break;
86  }
87  aptr += len;
88  if (aptr + RRFIXEDSZ > abuf + alen)
89  {
91  break;
92  }
93  rr_type = DNS_RR_TYPE (aptr);
94  rr_class = DNS_RR_CLASS (aptr);
95  rr_len = DNS_RR_LEN (aptr);
96  aptr += RRFIXEDSZ;
97  if (aptr + rr_len > abuf + alen)
98  {
100  break;
101  }
102 
103  /* Check if we are really looking at a SRV record */
104  if (rr_class == C_IN && rr_type == T_SRV)
105  {
106  /* parse the SRV record itself */
107  if (rr_len < 6)
108  {
110  break;
111  }
112 
113  /* Allocate storage for this SRV answer appending it to the list */
115  if (!srv_curr)
116  {
118  break;
119  }
120  if (srv_last)
121  {
122  srv_last->next = srv_curr;
123  }
124  else
125  {
126  srv_head = srv_curr;
127  }
128  srv_last = srv_curr;
129 
130  vptr = aptr;
131  srv_curr->priority = DNS__16BIT(vptr);
132  vptr += sizeof(unsigned short);
133  srv_curr->weight = DNS__16BIT(vptr);
134  vptr += sizeof(unsigned short);
135  srv_curr->port = DNS__16BIT(vptr);
136  vptr += sizeof(unsigned short);
137 
138  status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len);
139  if (status != ARES_SUCCESS)
140  break;
141  }
142 
143  /* Don't lose memory in the next iteration */
144  ares_free (rr_name);
145  rr_name = NULL;
146 
147  /* Move on to the next record */
148  aptr += rr_len;
149  }
150 
151  if (hostname)
152  ares_free (hostname);
153  if (rr_name)
154  ares_free (rr_name);
155 
156  /* clean up on error */
157  if (status != ARES_SUCCESS)
158  {
159  if (srv_head)
160  ares_free_data (srv_head);
161  return status;
162  }
163 
164  /* everything looks fine, return the data */
165  *srv_out = srv_head;
166 
167  return ARES_SUCCESS;
168 }
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
DNS_RR_LEN
#define DNS_RR_LEN(r)
Definition: ares_dns.h:104
T_SRV
#define T_SRV
Definition: ares_nameser.h:406
ares_srv_reply::weight
unsigned short weight
Definition: ares.h:543
ares.h
ares_dns.h
status
absl::Status status
Definition: rls.cc:251
ares_srv_reply::port
unsigned short port
Definition: ares.h:544
ares_srv_reply
Definition: ares.h:539
DNS_RR_TYPE
#define DNS_RR_TYPE(r)
Definition: ares_dns.h:101
ares_srv_reply::host
char * host
Definition: ares.h:541
DNS__16BIT
#define DNS__16BIT(p)
Definition: ares_dns.h:32
ARES_EBADRESP
#define ARES_EBADRESP
Definition: ares.h:112
ares_expand_name
CARES_EXTERN int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen)
Definition: ares_expand_name.c:203
ares_data.h
ARES_ENODATA
#define ARES_ENODATA
Definition: ares.h:101
DNS_RR_CLASS
#define DNS_RR_CLASS(r)
Definition: ares_dns.h:102
ares_parse_srv_reply
int ares_parse_srv_reply(const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out)
Definition: ares_parse_srv_reply.c:38
ares_srv_reply::priority
unsigned short priority
Definition: ares.h:542
RRFIXEDSZ
#define RRFIXEDSZ
Definition: ares_nameser.h:211
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
DNS_HEADER_QDCOUNT
#define DNS_HEADER_QDCOUNT(h)
Definition: ares_dns.h:72
ares_srv_reply::next
struct ares_srv_reply * next
Definition: ares.h:540
ares_setup.h
ares_free_data
CARES_EXTERN void ares_free_data(void *dataptr)
Definition: ares_data.c:41
C_IN
#define C_IN
Definition: ares_nameser.h:292
ares_malloc_data
void * ares_malloc_data(ares_datatype type)
Definition: ares_data.c:153
ares_free
void(* ares_free)(void *ptr)=default_free
Definition: ares_library_init.c:60
DNS_HEADER_ANCOUNT
#define DNS_HEADER_ANCOUNT(h)
Definition: ares_dns.h:73
ares_private.h
QFIXEDSZ
#define QFIXEDSZ
Definition: ares_nameser.h:207
HFIXEDSZ
#define HFIXEDSZ
Definition: ares_nameser.h:203
ARES_DATATYPE_SRV_REPLY
@ ARES_DATATYPE_SRV_REPLY
Definition: ares_data.h:19
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares_nameser.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:33