ares_parse_naptr_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_naptr_reply (const unsigned char *abuf, int alen,
39  struct ares_naptr_reply **naptr_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_naptr_reply *naptr_head = NULL;
47  struct ares_naptr_reply *naptr_last = NULL;
48  struct ares_naptr_reply *naptr_curr;
49 
50  /* Set *naptr_out to NULL for all failure cases. */
51  *naptr_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 NAPTR record */
104  if (rr_class == C_IN && rr_type == T_NAPTR)
105  {
106  /* parse the NAPTR record itself */
107 
108  /* RR must contain at least 7 bytes = 2 x int16 + 3 x name */
109  if (rr_len < 7)
110  {
112  break;
113  }
114 
115  /* Allocate storage for this NAPTR answer appending it to the list */
117  if (!naptr_curr)
118  {
120  break;
121  }
122  if (naptr_last)
123  {
124  naptr_last->next = naptr_curr;
125  }
126  else
127  {
128  naptr_head = naptr_curr;
129  }
130  naptr_last = naptr_curr;
131 
132  vptr = aptr;
133  naptr_curr->order = DNS__16BIT(vptr);
134  vptr += sizeof(unsigned short);
135  naptr_curr->preference = DNS__16BIT(vptr);
136  vptr += sizeof(unsigned short);
137 
138  status = ares_expand_string(vptr, abuf, alen, &naptr_curr->flags, &len);
139  if (status != ARES_SUCCESS)
140  break;
141  vptr += len;
142 
143  status = ares_expand_string(vptr, abuf, alen, &naptr_curr->service, &len);
144  if (status != ARES_SUCCESS)
145  break;
146  vptr += len;
147 
148  status = ares_expand_string(vptr, abuf, alen, &naptr_curr->regexp, &len);
149  if (status != ARES_SUCCESS)
150  break;
151  vptr += len;
152 
153  status = ares_expand_name(vptr, abuf, alen, &naptr_curr->replacement, &len);
154  if (status != ARES_SUCCESS)
155  break;
156  }
157 
158  /* Don't lose memory in the next iteration */
159  ares_free (rr_name);
160  rr_name = NULL;
161 
162  /* Move on to the next record */
163  aptr += rr_len;
164  }
165 
166  if (hostname)
167  ares_free (hostname);
168  if (rr_name)
169  ares_free (rr_name);
170 
171  /* clean up on error */
172  if (status != ARES_SUCCESS)
173  {
174  if (naptr_head)
175  ares_free_data (naptr_head);
176  return status;
177  }
178 
179  /* everything looks fine, return the data */
180  *naptr_out = naptr_head;
181 
182  return ARES_SUCCESS;
183 }
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
ares_parse_naptr_reply
int ares_parse_naptr_reply(const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out)
Definition: ares_parse_naptr_reply.c:38
DNS_RR_LEN
#define DNS_RR_LEN(r)
Definition: ares_dns.h:104
ares.h
ares_expand_string
CARES_EXTERN int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf, int alen, unsigned char **s, long *enclen)
Definition: ares_expand_string.c:33
ares_dns.h
status
absl::Status status
Definition: rls.cc:251
DNS_RR_TYPE
#define DNS_RR_TYPE(r)
Definition: ares_dns.h:101
ares_naptr_reply::regexp
unsigned char * regexp
Definition: ares.h:574
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_naptr_reply::service
unsigned char * service
Definition: ares.h:573
ARES_DATATYPE_NAPTR_REPLY
@ ARES_DATATYPE_NAPTR_REPLY
Definition: ares_data.h:24
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_naptr_reply::next
struct ares_naptr_reply * next
Definition: ares.h:571
ares_naptr_reply
Definition: ares.h:570
ares_naptr_reply::flags
unsigned char * flags
Definition: ares.h:572
T_NAPTR
#define T_NAPTR
Definition: ares_nameser.h:412
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_setup.h
ares_naptr_reply::order
unsigned short order
Definition: ares.h:576
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
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares_nameser.h
ares_naptr_reply::preference
unsigned short preference
Definition: ares.h:577
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
ares_naptr_reply::replacement
char * replacement
Definition: ares.h:575


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:43