ares_parse_ns_reply.c
Go to the documentation of this file.
1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2  *
3  * Permission to use, copy, modify, and distribute this
4  * software and its documentation for any purpose and without
5  * fee is hereby granted, provided that the above copyright
6  * notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting
8  * documentation, and that the name of M.I.T. not be used in
9  * advertising or publicity pertaining to distribution of the
10  * software without specific, written prior permission.
11  * M.I.T. makes no representations about the suitability of
12  * this software for any purpose. It is provided "as is"
13  * without express or implied warranty.
14  */
15 
16 /*
17  * ares_parse_ns_reply created by Vlad Dinulescu <vlad.dinulescu@avira.com>
18  * on behalf of AVIRA Gmbh - http://www.avira.com
19  */
20 
21 #include "ares_setup.h"
22 
23 #ifdef HAVE_NETINET_IN_H
24 # include <netinet/in.h>
25 #endif
26 #ifdef HAVE_NETDB_H
27 # include <netdb.h>
28 #endif
29 #ifdef HAVE_ARPA_INET_H
30 # include <arpa/inet.h>
31 #endif
32 
33 #include "ares_nameser.h"
34 
35 #include "ares.h"
36 #include "ares_dns.h"
37 #include "ares_private.h"
38 
39 int ares_parse_ns_reply( const unsigned char* abuf, int alen,
40  struct hostent** host )
41 {
42  unsigned int qdcount, ancount;
43  int status, i, rr_type, rr_class, rr_len;
44  int nameservers_num;
45  long len;
46  const unsigned char *aptr;
47  char* hostname, *rr_name, *rr_data, **nameservers;
48  struct hostent *hostent;
49 
50  /* Set *host to NULL for all failure cases. */
51  *host = 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 
63  /* Expand the name from the question, and skip past the question. */
64  aptr = abuf + HFIXEDSZ;
65  status = ares__expand_name_for_response( aptr, abuf, alen, &hostname, &len, 0);
66  if ( status != ARES_SUCCESS )
67  return status;
68  if ( aptr + len + QFIXEDSZ > abuf + alen )
69  {
70  ares_free( hostname );
71  return ARES_EBADRESP;
72  }
73  aptr += len + QFIXEDSZ;
74 
75  /* Allocate nameservers array; ancount gives an upper bound */
76  nameservers = ares_malloc( ( ancount + 1 ) * sizeof( char * ) );
77  if ( !nameservers )
78  {
79  ares_free( hostname );
80  return ARES_ENOMEM;
81  }
82  nameservers_num = 0;
83 
84  /* Examine each answer resource record (RR) in turn. */
85  for ( i = 0; i < ( int ) ancount; i++ )
86  {
87  /* Decode the RR up to the data field. */
88  status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len, 0);
89  if ( status != ARES_SUCCESS )
90  break;
91  aptr += len;
92  if ( aptr + RRFIXEDSZ > abuf + alen )
93  {
95  ares_free(rr_name);
96  break;
97  }
98  rr_type = DNS_RR_TYPE( aptr );
99  rr_class = DNS_RR_CLASS( aptr );
100  rr_len = DNS_RR_LEN( aptr );
101  aptr += RRFIXEDSZ;
102  if (aptr + rr_len > abuf + alen)
103  {
104  ares_free(rr_name);
106  break;
107  }
108 
109  if ( rr_class == C_IN && rr_type == T_NS )
110  {
111  /* Decode the RR data and add it to the nameservers list */
112  status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data,
113  &len, 1);
114  if ( status != ARES_SUCCESS )
115  {
116  ares_free(rr_name);
117  break;
118  }
119 
120  nameservers[nameservers_num] = ares_malloc(strlen(rr_data)+1);
121 
122  if (nameservers[nameservers_num]==NULL)
123  {
124  ares_free(rr_name);
125  ares_free(rr_data);
127  break;
128  }
129  strcpy(nameservers[nameservers_num],rr_data);
130  ares_free(rr_data);
131 
132  nameservers_num++;
133  }
134 
135  ares_free( rr_name );
136 
137  aptr += rr_len;
138  if ( aptr > abuf + alen )
139  { /* LCOV_EXCL_START: already checked above */
141  break;
142  } /* LCOV_EXCL_STOP */
143  }
144 
145  if ( status == ARES_SUCCESS && nameservers_num == 0 )
146  {
148  }
149  if ( status == ARES_SUCCESS )
150  {
151  /* We got our answer. Allocate memory to build the host entry. */
152  nameservers[nameservers_num] = NULL;
153  hostent = ares_malloc( sizeof( struct hostent ) );
154  if ( hostent )
155  {
156  hostent->h_addr_list = ares_malloc( 1 * sizeof( char * ) );
157  if ( hostent->h_addr_list )
158  {
159  /* Fill in the hostent and return successfully. */
160  hostent->h_name = hostname;
161  hostent->h_aliases = nameservers;
162  hostent->h_addrtype = AF_INET;
163  hostent->h_length = sizeof( struct in_addr );
164  hostent->h_addr_list[0] = NULL;
165  *host = hostent;
166  return ARES_SUCCESS;
167  }
168  ares_free( hostent );
169  }
171  }
172  for ( i = 0; i < nameservers_num; i++ )
173  ares_free( nameservers[i] );
174  ares_free( nameservers );
175  ares_free( hostname );
176  return status;
177 }
T_NS
#define T_NS
Definition: ares_nameser.h:313
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
DNS_RR_LEN
#define DNS_RR_LEN(r)
Definition: ares_dns.h:104
ares.h
ares__expand_name_for_response
int ares__expand_name_for_response(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen, int is_hostname)
Definition: ares_expand_name.c:291
ares_dns.h
status
absl::Status status
Definition: rls.cc:251
ares_parse_ns_reply
int ares_parse_ns_reply(const unsigned char *abuf, int alen, struct hostent **host)
Definition: ares_parse_ns_reply.c:39
DNS_RR_TYPE
#define DNS_RR_TYPE(r)
Definition: ares_dns.h:101
ARES_EBADRESP
#define ARES_EBADRESP
Definition: ares.h:112
ares_malloc
void *(* ares_malloc)(size_t size)=default_malloc
Definition: ares_library_init.c:58
xds_interop_client.int
int
Definition: xds_interop_client.py:113
ARES_ENODATA
#define ARES_ENODATA
Definition: ares.h:101
DNS_RR_CLASS
#define DNS_RR_CLASS(r)
Definition: ares_dns.h:102
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
C_IN
#define C_IN
Definition: ares_nameser.h:292
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
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


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