ares_options.c
Go to the documentation of this file.
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  * Copyright (C) 2008-2013 by Daniel Stenberg
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 
19 #include "ares_setup.h"
20 
21 #ifdef HAVE_ARPA_INET_H
22 # include <arpa/inet.h>
23 #endif
24 
25 #include "ares.h"
26 #include "ares_data.h"
27 #include "ares_inet_net_pton.h"
28 #include "ares_private.h"
29 
30 
32  struct ares_addr_node **servers)
33 {
34  struct ares_addr_node *srvr_head = NULL;
35  struct ares_addr_node *srvr_last = NULL;
36  struct ares_addr_node *srvr_curr;
37  int status = ARES_SUCCESS;
38  int i;
39 
40  if (!channel)
41  return ARES_ENODATA;
42 
43  for (i = 0; i < channel->nservers; i++)
44  {
45  /* Allocate storage for this server node appending it to the list */
47  if (!srvr_curr)
48  {
50  break;
51  }
52  if (srvr_last)
53  {
54  srvr_last->next = srvr_curr;
55  }
56  else
57  {
58  srvr_head = srvr_curr;
59  }
60  srvr_last = srvr_curr;
61 
62  /* Fill this server node data */
63  srvr_curr->family = channel->servers[i].addr.family;
64  if (srvr_curr->family == AF_INET)
65  memcpy(&srvr_curr->addrV4, &channel->servers[i].addr.addrV4,
66  sizeof(srvr_curr->addrV4));
67  else
68  memcpy(&srvr_curr->addrV6, &channel->servers[i].addr.addrV6,
69  sizeof(srvr_curr->addrV6));
70  }
71 
72  if (status != ARES_SUCCESS)
73  {
74  if (srvr_head)
75  {
76  ares_free_data(srvr_head);
77  srvr_head = NULL;
78  }
79  }
80 
81  *servers = srvr_head;
82 
83  return status;
84 }
85 
88 {
89  struct ares_addr_port_node *srvr_head = NULL;
90  struct ares_addr_port_node *srvr_last = NULL;
91  struct ares_addr_port_node *srvr_curr;
92  int status = ARES_SUCCESS;
93  int i;
94 
95  if (!channel)
96  return ARES_ENODATA;
97 
98  for (i = 0; i < channel->nservers; i++)
99  {
100  /* Allocate storage for this server node appending it to the list */
102  if (!srvr_curr)
103  {
105  break;
106  }
107  if (srvr_last)
108  {
109  srvr_last->next = srvr_curr;
110  }
111  else
112  {
113  srvr_head = srvr_curr;
114  }
115  srvr_last = srvr_curr;
116 
117  /* Fill this server node data */
118  srvr_curr->family = channel->servers[i].addr.family;
119  srvr_curr->udp_port = ntohs((unsigned short)channel->servers[i].addr.udp_port);
120  srvr_curr->tcp_port = ntohs((unsigned short)channel->servers[i].addr.tcp_port);
121  if (srvr_curr->family == AF_INET)
122  memcpy(&srvr_curr->addrV4, &channel->servers[i].addr.addrV4,
123  sizeof(srvr_curr->addrV4));
124  else
125  memcpy(&srvr_curr->addrV6, &channel->servers[i].addr.addrV6,
126  sizeof(srvr_curr->addrV6));
127  }
128 
129  if (status != ARES_SUCCESS)
130  {
131  if (srvr_head)
132  {
133  ares_free_data(srvr_head);
134  srvr_head = NULL;
135  }
136  }
137 
138  *servers = srvr_head;
139 
140  return status;
141 }
142 
144  struct ares_addr_node *servers)
145 {
146  struct ares_addr_node *srvr;
147  int num_srvrs = 0;
148  int i;
149 
151  return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
152 
153  if (!channel)
154  return ARES_ENODATA;
155 
156  if (!ares__is_list_empty(&channel->all_queries))
157  return ARES_ENOTIMP;
158 
160 
161  for (srvr = servers; srvr; srvr = srvr->next)
162  {
163  num_srvrs++;
164  }
165 
166  if (num_srvrs > 0)
167  {
168  /* Allocate storage for servers state */
169  channel->servers = ares_malloc(num_srvrs * sizeof(struct server_state));
170  if (!channel->servers)
171  {
172  return ARES_ENOMEM;
173  }
174  channel->nservers = num_srvrs;
175  /* Fill servers state address data */
176  for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next)
177  {
178  channel->servers[i].addr.family = srvr->family;
179  channel->servers[i].addr.udp_port = 0;
180  channel->servers[i].addr.tcp_port = 0;
181  if (srvr->family == AF_INET)
182  memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4,
183  sizeof(srvr->addrV4));
184  else
185  memcpy(&channel->servers[i].addr.addrV6, &srvr->addrV6,
186  sizeof(srvr->addrV6));
187  }
188  /* Initialize servers state remaining data */
190  }
191 
192  return ARES_SUCCESS;
193 }
194 
197 {
198  struct ares_addr_port_node *srvr;
199  int num_srvrs = 0;
200  int i;
201 
203  return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
204 
205  if (!channel)
206  return ARES_ENODATA;
207 
208  if (!ares__is_list_empty(&channel->all_queries))
209  return ARES_ENOTIMP;
210 
212 
213  for (srvr = servers; srvr; srvr = srvr->next)
214  {
215  num_srvrs++;
216  }
217 
218  if (num_srvrs > 0)
219  {
220  /* Allocate storage for servers state */
221  channel->servers = ares_malloc(num_srvrs * sizeof(struct server_state));
222  if (!channel->servers)
223  {
224  return ARES_ENOMEM;
225  }
226  channel->nservers = num_srvrs;
227  /* Fill servers state address data */
228  for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next)
229  {
230  channel->servers[i].addr.family = srvr->family;
231  channel->servers[i].addr.udp_port = htons((unsigned short)srvr->udp_port);
232  channel->servers[i].addr.tcp_port = htons((unsigned short)srvr->tcp_port);
233  if (srvr->family == AF_INET)
234  memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4,
235  sizeof(srvr->addrV4));
236  else
237  memcpy(&channel->servers[i].addr.addrV6, &srvr->addrV6,
238  sizeof(srvr->addrV6));
239  }
240  /* Initialize servers state remaining data */
242  }
243 
244  return ARES_SUCCESS;
245 }
246 
247 /* Incomming string format: host[:port][,host[:port]]... */
248 /* IPv6 addresses with ports require square brackets [fe80::1%lo0]:53 */
250  const char* _csv, int use_port)
251 {
252  size_t i;
253  char* csv = NULL;
254  char* ptr;
255  char* start_host;
256  int cc = 0;
257  int rv = ARES_SUCCESS;
258  struct ares_addr_port_node *servers = NULL;
259  struct ares_addr_port_node *last = NULL;
260 
262  return ARES_ENOTINITIALIZED; /* LCOV_EXCL_LINE: n/a on non-WinSock */
263 
264  if (!channel)
265  return ARES_ENODATA;
266 
267  i = strlen(_csv);
268  if (i == 0)
269  return ARES_SUCCESS; /* blank all servers */
270 
271  csv = ares_malloc(i + 2);
272  if (!csv)
273  return ARES_ENOMEM;
274 
275  strcpy(csv, _csv);
276  if (csv[i-1] != ',') { /* make parsing easier by ensuring ending ',' */
277  csv[i] = ',';
278  csv[i+1] = 0;
279  }
280 
281  start_host = csv;
282  for (ptr = csv; *ptr; ptr++) {
283  if (*ptr == ':') {
284  /* count colons to determine if we have an IPv6 number or IPv4 with
285  port */
286  cc++;
287  }
288  else if (*ptr == '[') {
289  /* move start_host if an open square bracket is found wrapping an IPv6
290  address */
291  start_host = ptr + 1;
292  }
293  else if (*ptr == ',') {
294  char* pp = ptr - 1;
295  char* p = ptr;
296  int port = 0;
297  struct in_addr in4;
298  struct ares_in6_addr in6;
299  struct ares_addr_port_node *s = NULL;
300 
301  *ptr = 0; /* null terminate host:port string */
302  /* Got an entry..see if the port was specified. */
303  if (cc > 0) {
304  while (pp > start_host) {
305  /* a single close square bracket followed by a colon, ']:' indicates
306  an IPv6 address with port */
307  if ((*pp == ']') && (*p == ':'))
308  break; /* found port */
309  /* a single colon, ':' indicates an IPv4 address with port */
310  if ((*pp == ':') && (cc == 1))
311  break; /* found port */
312  if (!(ISDIGIT(*pp) || (*pp == ':'))) {
313  /* Found end of digits before we found :, so wasn't a port */
314  /* must allow ':' for IPv6 case of ']:' indicates we found a port */
315  pp = p = ptr;
316  break;
317  }
318  pp--;
319  p--;
320  }
321  if ((pp != start_host) && ((pp + 1) < ptr)) {
322  /* Found it. Parse over the port number */
323  /* when an IPv6 address is wrapped with square brackets the port
324  starts at pp + 2 */
325  if (*pp == ']')
326  p++; /* move p before ':' */
327  /* p will point to the start of the port */
328  port = (int)strtol(p, NULL, 10);
329  *pp = 0; /* null terminate host */
330  }
331  }
332  /* resolve host, try ipv4 first, rslt is in network byte order */
333  rv = ares_inet_pton(AF_INET, start_host, &in4);
334  if (!rv) {
335  /* Ok, try IPv6 then */
336  rv = ares_inet_pton(AF_INET6, start_host, &in6);
337  if (!rv) {
338  rv = ARES_EBADSTR;
339  goto out;
340  }
341  /* was ipv6, add new server */
342  s = ares_malloc(sizeof(*s));
343  if (!s) {
344  rv = ARES_ENOMEM;
345  goto out;
346  }
347  s->family = AF_INET6;
348  memcpy(&s->addr, &in6, sizeof(struct ares_in6_addr));
349  }
350  else {
351  /* was ipv4, add new server */
352  s = ares_malloc(sizeof(*s));
353  if (!s) {
354  rv = ARES_ENOMEM;
355  goto out;
356  }
357  s->family = AF_INET;
358  memcpy(&s->addr, &in4, sizeof(struct in_addr));
359  }
360  if (s) {
361  s->udp_port = use_port ? port: 0;
362  s->tcp_port = s->udp_port;
363  s->next = NULL;
364  if (last) {
365  last->next = s;
366  /* need to move last to maintain the linked list */
367  last = last->next;
368  }
369  else {
370  servers = s;
371  last = s;
372  }
373  }
374 
375  /* Set up for next one */
376  start_host = ptr + 1;
377  cc = 0;
378  }
379  }
380 
382 
383  out:
384  if (csv)
385  ares_free(csv);
386  while (servers) {
387  struct ares_addr_port_node *s = servers;
388  servers = servers->next;
389  ares_free(s);
390  }
391 
392  return rv;
393 }
394 
396  const char* _csv)
397 {
398  return set_servers_csv(channel, _csv, FALSE);
399 }
400 
402  const char* _csv)
403 {
404  return set_servers_csv(channel, _csv, TRUE);
405 }
406 
TRUE
const BOOL TRUE
Definition: undname.c:48
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
ares_set_servers
int ares_set_servers(ares_channel channel, struct ares_addr_node *servers)
Definition: ares_options.c:143
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
server_state
Definition: ares_private.h:161
ares_get_servers
int ares_get_servers(ares_channel channel, struct ares_addr_node **servers)
Definition: ares_options.c:31
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
ares_inet_pton
CARES_EXTERN int ares_inet_pton(int af, const char *src, void *dst)
Definition: inet_net_pton.c:418
ares_addr_node::family
int family
Definition: ares.h:697
ares__init_servers_state
void ares__init_servers_state(ares_channel channel)
Definition: ares_init.c:2633
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
ares_set_servers_csv
int ares_set_servers_csv(ares_channel channel, const char *_csv)
Definition: ares_options.c:395
ares.h
ares_addr_port_node
Definition: ares.h:704
ISDIGIT
#define ISDIGIT(x)
Definition: setup_once.h:276
ares_addr_node
Definition: ares.h:695
ares_inet_net_pton.h
status
absl::Status status
Definition: rls.cc:251
ares_get_servers_ports
int ares_get_servers_ports(ares_channel channel, struct ares_addr_port_node **servers)
Definition: ares_options.c:86
ares_addr_node::next
struct ares_addr_node * next
Definition: ares.h:696
xds_manager.p
p
Definition: xds_manager.py:60
ares_library_initialized
CARES_EXTERN int ares_library_initialized(void)
Definition: ares_library_init.c:193
ares__is_list_empty
int ares__is_list_empty(struct list_node *head)
Definition: ares_llist.c:41
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
channel
wrapped_grpc_channel * channel
Definition: src/php/ext/grpc/call.h:33
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_data.h
ARES_ENODATA
#define ARES_ENODATA
Definition: ares.h:101
ARES_EBADSTR
#define ARES_EBADSTR
Definition: ares.h:119
set_servers_csv
static int set_servers_csv(ares_channel channel, const char *_csv, int use_port)
Definition: ares_options.c:249
ARES_ENOTINITIALIZED
#define ARES_ENOTINITIALIZED
Definition: ares.h:129
ares_addr_port_node::family
int family
Definition: ares.h:706
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
ares_setup.h
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
pp
const uint8_t ** pp
Definition: ssl_x509.cc:1020
ares_channeldata
Definition: ares_private.h:266
FALSE
const BOOL FALSE
Definition: undname.c:47
ARES_DATATYPE_ADDR_PORT_NODE
@ ARES_DATATYPE_ADDR_PORT_NODE
Definition: ares_data.h:32
ares_free_data
CARES_EXTERN void ares_free_data(void *dataptr)
Definition: ares_data.c:41
ares_set_servers_ports
int ares_set_servers_ports(ares_channel channel, struct ares_addr_port_node *servers)
Definition: ares_options.c:195
ares_in6_addr
Definition: ares.h:514
ares_malloc_data
void * ares_malloc_data(ares_datatype type)
Definition: ares_data.c:153
ares_addr_port_node::next
struct ares_addr_port_node * next
Definition: ares.h:705
ares_free
void(* ares_free)(void *ptr)=default_free
Definition: ares_library_init.c:60
ares_addr_port_node::tcp_port
int tcp_port
Definition: ares.h:712
ARES_DATATYPE_ADDR_NODE
@ ARES_DATATYPE_ADDR_NODE
Definition: ares_data.h:22
ares_private.h
ares_set_servers_ports_csv
int ares_set_servers_ports_csv(ares_channel channel, const char *_csv)
Definition: ares_options.c:401
ARES_ENOTIMP
#define ARES_ENOTIMP
Definition: ares.h:105
run_interop_tests.servers
servers
Definition: run_interop_tests.py:1288
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
ares_addr_port_node::udp_port
int udp_port
Definition: ares.h:711
ares__destroy_servers_state
void ares__destroy_servers_state(ares_channel channel)
Definition: ares_destroy.c:96


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