Indents are 8 characters wide and are expressed as a tab character.
[citadel.git] / citadel / modules / c-ares-dns / serv_c-ares-dns.c
1 /*
2  * Copyright (c) 1998-2017 by the citadel.org team
3  *
4  * This program is open source software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 3.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * Inspired by NodeJS.org; thanks for the MX-Parser ;-)
13  */
14
15 #include "sysdep.h"
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <termios.h>
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <pwd.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <syslog.h>
26
27 #if TIME_WITH_SYS_TIME
28 # include <sys/time.h>
29 # include <time.h>
30 #else
31 # if HAVE_SYS_TIME_H
32 #  include <sys/time.h>
33 # else
34 #  include <time.h>
35 # endif
36 #endif
37 #include <sys/wait.h>
38 #include <ctype.h>
39 #include <string.h>
40 #include <limits.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44
45 #include <libcitadel.h>
46 #include "citadel.h"
47 #include "server.h"
48 #include "citserver.h"
49 #include "support.h"
50
51 #include "ctdl_module.h"
52 #include "event_client.h"
53
54 int DebugCAres = 0;
55
56 extern struct ev_loop *event_base;
57
58 void SockStateCb(void *data, int sock, int read, int write);
59
60
61 static void HostByAddrCb(void *data,
62                          int status,
63                          int timeouts,
64                          struct hostent *hostent)
65 {
66         AsyncIO *IO = data;
67
68         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
69
70         EV_DNS_LOGT_STOP(DNS.timeout);
71         ev_timer_stop (event_base, &IO->DNS.timeout);
72
73         IO->DNS.Query->DNSStatus = status;
74         if  (status != ARES_SUCCESS) {
75                 StrBufPlain(IO->ErrMsg, ares_strerror(status), -1);
76                 return;
77         }
78         IO->DNS.Query->Data = hostent;
79 }
80
81 static void ParseAnswerA(AsyncIO *IO, unsigned char* abuf, int alen)
82 {
83         struct hostent* host = NULL;
84
85         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
86
87         if (IO->DNS.Query->VParsedDNSReply != NULL)
88                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
89         IO->DNS.Query->VParsedDNSReply = NULL;
90
91         IO->DNS.Query->DNSStatus = ares_parse_a_reply(abuf,
92                                                       alen,
93                                                       &host,
94                                                       NULL,
95                                                       NULL);
96         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
97                 if (host != NULL)
98                         ares_free_hostent(host);
99                 StrBufPlain(IO->ErrMsg,
100                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
101                 return;
102         }
103         IO->DNS.Query->VParsedDNSReply = host;
104         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent;
105 }
106
107
108 static void ParseAnswerAAAA(AsyncIO *IO, unsigned char* abuf, int alen)
109 {
110         struct hostent* host = NULL;
111
112         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
113
114         if (IO->DNS.Query->VParsedDNSReply != NULL)
115                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
116         IO->DNS.Query->VParsedDNSReply = NULL;
117
118         IO->DNS.Query->DNSStatus = ares_parse_aaaa_reply(abuf,
119                                                          alen,
120                                                          &host,
121                                                          NULL,
122                                                          NULL);
123         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
124                 if (host != NULL)
125                         ares_free_hostent(host);
126                 StrBufPlain(IO->ErrMsg,
127                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
128                 return;
129         }
130         IO->DNS.Query->VParsedDNSReply = host;
131         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent;
132 }
133
134
135 static void ParseAnswerCNAME(AsyncIO *IO, unsigned char* abuf, int alen)
136 {
137         struct hostent* host = NULL;
138
139         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
140
141         if (IO->DNS.Query->VParsedDNSReply != NULL)
142                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
143         IO->DNS.Query->VParsedDNSReply = NULL;
144
145         IO->DNS.Query->DNSStatus = ares_parse_a_reply(abuf,
146                                                       alen,
147                                                       &host,
148                                                       NULL,
149                                                       NULL);
150         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
151                 if (host != NULL)
152                         ares_free_hostent(host);
153                 StrBufPlain(IO->ErrMsg,
154                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
155                 return;
156         }
157
158         // a CNAME lookup always returns a single record but
159         IO->DNS.Query->VParsedDNSReply = host;
160         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent;
161 }
162
163
164 static void ParseAnswerMX(AsyncIO *IO, unsigned char* abuf, int alen)
165 {
166         struct ares_mx_reply *mx_out = NULL;
167
168         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
169
170         if (IO->DNS.Query->VParsedDNSReply != NULL)
171                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
172         IO->DNS.Query->VParsedDNSReply = NULL;
173
174         IO->DNS.Query->DNSStatus = ares_parse_mx_reply(abuf, alen, &mx_out);
175         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
176                 if (mx_out != NULL)
177                         ares_free_data(mx_out);
178                 StrBufPlain(IO->ErrMsg,
179                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
180                 return;
181         }
182
183         IO->DNS.Query->VParsedDNSReply = mx_out;
184         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data;
185 }
186
187
188 static void ParseAnswerNS(AsyncIO *IO, unsigned char* abuf, int alen)
189 {
190         struct hostent* host = NULL;
191
192         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
193
194         if (IO->DNS.Query->VParsedDNSReply != NULL)
195                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
196         IO->DNS.Query->VParsedDNSReply = NULL;
197
198         IO->DNS.Query->DNSStatus = ares_parse_ns_reply(abuf, alen, &host);
199         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
200                 if (host != NULL)
201                         ares_free_hostent(host);
202                 StrBufPlain(IO->ErrMsg,
203                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
204                 return;
205         }
206         IO->DNS.Query->VParsedDNSReply = host;
207         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent;
208 }
209
210
211 static void ParseAnswerSRV(AsyncIO *IO, unsigned char* abuf, int alen)
212 {
213         struct ares_srv_reply *srv_out = NULL;
214
215         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
216
217         if (IO->DNS.Query->VParsedDNSReply != NULL)
218                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
219         IO->DNS.Query->VParsedDNSReply = NULL;
220
221         IO->DNS.Query->DNSStatus = ares_parse_srv_reply(abuf, alen, &srv_out);
222         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
223                 if (srv_out != NULL)
224                         ares_free_data(srv_out);
225                 StrBufPlain(IO->ErrMsg,
226                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
227                 return;
228         }
229
230         IO->DNS.Query->VParsedDNSReply = srv_out;
231         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data;
232 }
233
234
235 static void ParseAnswerTXT(AsyncIO *IO, unsigned char* abuf, int alen)
236 {
237         struct ares_txt_reply *txt_out;
238
239         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
240
241         if (IO->DNS.Query->VParsedDNSReply != NULL)
242                 IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply);
243         IO->DNS.Query->VParsedDNSReply = NULL;
244
245         IO->DNS.Query->DNSStatus = ares_parse_txt_reply(abuf, alen, &txt_out);
246         if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) {
247                 if (txt_out != NULL)
248                         ares_free_data(txt_out);
249                 StrBufPlain(IO->ErrMsg,
250                             ares_strerror(IO->DNS.Query->DNSStatus), -1);
251                 return;
252         }
253         IO->DNS.Query->VParsedDNSReply = txt_out;
254         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data;
255 }
256
257 void QueryCb(void *arg,
258              int status,
259              int timeouts,
260              unsigned char* abuf,
261              int alen)
262 {
263         AsyncIO *IO = arg;
264
265         SetEVState(IO, eCaresStart);
266         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
267
268         EV_DNS_LOGT_STOP(DNS.timeout);
269         ev_timer_stop (event_base, &IO->DNS.timeout);
270
271         IO->DNS.Query->DNSStatus = status;
272         if (status == ARES_SUCCESS)
273                 IO->DNS.Query->DNS_CB(arg, abuf, alen);
274         else {
275                 syslog(LOG_DEBUG, "c-ares: Failed by: %s error %s", __FUNCTION__, ares_strerror(status));
276                 StrBufPrintf(IO->ErrMsg,
277                              "%s-lookup %s - %s",
278                              IO->DNS.Query->QueryTYPE,
279                              (IO->DNS.Query->QStr != NULL)? IO->DNS.Query->QStr : "",
280                              ares_strerror(status));
281                 IO->DNS.Query->DNSStatus = status;
282         }
283
284         ev_idle_init(&IO->unwind_stack,
285                      IO_postdns_callback);
286         IO->unwind_stack.data = IO;
287         EV_DNS_LOGT_INIT(unwind_stack);
288         EV_DNS_LOGT_START(unwind_stack);
289         ev_idle_start(event_base, &IO->unwind_stack);
290 }
291
292 void QueryCbDone(AsyncIO *IO)
293 {
294         SetEVState(IO, eCaresDoneIO);
295         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
296
297         EV_DNS_LOGT_STOP(DNS.timeout);
298         ev_timer_stop (event_base, &IO->DNS.timeout);
299
300         EV_DNS_LOGT_STOP(unwind_stack);
301         ev_idle_stop(event_base, &IO->unwind_stack);
302 }
303
304 void DestructCAres(AsyncIO *IO)
305 {
306         SetEVState(IO, eCaresX);
307         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
308         syslog(LOG_DEBUG, "c-ares: stopping %s %d %p", "DNS.recv_event", IO->DNS.recv_event.fd, &IO->DNS.recv_event);
309         ev_io_stop(event_base, &IO->DNS.recv_event);
310         syslog(LOG_DEBUG, "c-ares: stopping %s %d %p", "DNS.send_event", IO->DNS.send_event.fd, &IO->DNS.send_event);
311         ev_io_stop(event_base, &IO->DNS.send_event);
312         syslog(LOG_DEBUG, "c-ares: stopping %s %p", "DNS.timeout", &IO->DNS.send_event);
313         ev_timer_stop (event_base, &IO->DNS.timeout);
314         syslog(LOG_DEBUG, "c-ares: stopping %s %p", "DNS.unwind_stack", &IO->unwind_stack);
315         ev_idle_stop(event_base, &IO->unwind_stack);
316         ares_destroy_options(&IO->DNS.Options);
317 }
318
319
320 void InitC_ares_dns(AsyncIO *IO)
321 {
322         int optmask = 0;
323
324         syslog(LOG_DEBUG, "c-ares: %s %p", __FUNCTION__, IO->DNS.Channel);
325
326         if (IO->DNS.Channel == NULL) {
327                 optmask |= ARES_OPT_SOCK_STATE_CB;
328                 IO->DNS.Options.sock_state_cb = SockStateCb;
329                 IO->DNS.Options.sock_state_cb_data = IO;
330                 ares_init_options(&IO->DNS.Channel, &IO->DNS.Options, optmask);
331         }
332         IO->DNS.Query->DNSStatus = 0;
333 }
334
335 static void
336 DNStimeouttrigger_callback(struct ev_loop *loop, ev_timer *watcher, int revents)
337 {
338         AsyncIO *IO = watcher->data;
339         struct timeval tv, MaxTV;
340         struct timeval *NextTV;
341
342         memset(&MaxTV, 0, sizeof(MaxTV));
343         memset(&tv, 0, sizeof(tv));
344         MaxTV.tv_sec = 30;
345         NextTV = ares_timeout(IO->DNS.Channel, &MaxTV, &tv);
346
347         if ((NextTV->tv_sec != MaxTV.tv_sec) ||
348             (NextTV->tv_usec != MaxTV.tv_usec))
349         {
350                 fd_set readers, writers;
351                 syslog(LOG_DEBUG, "c-ares: %s Timeout!", __FUNCTION__);
352
353                 FD_ZERO(&readers);
354                 FD_ZERO(&writers);
355                 ares_fds(IO->DNS.Channel, &readers, &writers);
356                 ares_process(IO->DNS.Channel, &readers, &writers);
357         }
358 }
359
360 void QueueGetHostByNameDone(void *Ctx,
361                             int status,
362                             int timeouts,
363                             struct hostent *hostent)
364 {
365         AsyncIO *IO = (AsyncIO *) Ctx;
366
367         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
368
369
370         IO->DNS.Query->DNSStatus = status;
371         IO->DNS.Query->VParsedDNSReply = hostent;
372         IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent;
373
374         EV_DNS_LOGT_STOP(DNS.timeout);
375         ev_timer_stop (event_base, &IO->DNS.timeout);
376
377         ev_idle_init(&IO->unwind_stack,
378                      IO_postdns_callback);
379         IO->unwind_stack.data = IO;
380         EV_DNS_LOGT_INIT(unwind_stack);
381         EV_DNS_LOGT_START(unwind_stack);
382         ev_idle_start(event_base, &IO->unwind_stack);
383
384 }
385
386 void QueueGetHostByName(AsyncIO *IO,
387                         const char *Hostname,
388                         DNSQueryParts *QueryParts,
389                         IO_CallBack PostDNS)
390 {
391
392         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
393         IO->DNS.SourcePort = 0;
394
395         IO->DNS.Query = QueryParts;
396         IO->DNS.Query->PostDNS = PostDNS;
397
398         InitC_ares_dns(IO);
399
400         ev_timer_init(&IO->DNS.timeout, DNStimeouttrigger_callback, 10, 1);
401         EV_DNS_LOGT_INIT(DNS.timeout);
402         IO->DNS.timeout.data = IO;
403         ares_gethostbyname(IO->DNS.Channel,
404                            Hostname,
405                            AF_INET6, /* it falls back to ipv4 in doubt... */
406                            QueueGetHostByNameDone,
407                            IO);
408         EV_DNS_LOGT_START(DNS.timeout);
409         ev_timer_start(event_base, &IO->DNS.timeout);
410
411 }
412
413 const char* QT[] = {
414         "A",
415         "AAAA",
416         "MX",
417         "NS",
418         "TXT",
419         "SRV",
420         "CNAME",
421         "PTR"
422 };
423
424 int QueueQuery(ns_type Type,
425                const char *name,
426                AsyncIO *IO,
427                DNSQueryParts *QueryParts,
428                IO_CallBack PostDNS)
429 {
430         int length, family;
431         char address_b[sizeof(struct in6_addr)];
432
433         IO->DNS.SourcePort = 0;
434
435         IO->DNS.Query = QueryParts;
436         IO->DNS.Query->PostDNS = PostDNS;
437         IO->DNS.Start = IO->Now;
438         IO->DNS.Query->QStr = name;
439
440         InitC_ares_dns(IO);
441
442         ev_timer_init(&IO->DNS.timeout, DNStimeouttrigger_callback, 10, 1);
443         IO->DNS.timeout.data = IO;
444         EV_DNS_LOGT_INIT(DNS.timeout);
445
446         switch(Type) {
447         case ns_t_a:
448                 IO->DNS.Query->DNS_CB = ParseAnswerA;
449                 IO->DNS.Query->QueryTYPE = QT[0];
450                 break;
451
452         case ns_t_aaaa:
453                 IO->DNS.Query->DNS_CB = ParseAnswerAAAA;
454                 IO->DNS.Query->QueryTYPE = QT[1];
455                 break;
456
457         case ns_t_mx:
458                 IO->DNS.Query->DNS_CB = ParseAnswerMX;
459                 IO->DNS.Query->QueryTYPE = QT[2];
460                 break;
461
462         case ns_t_ns:
463                 IO->DNS.Query->DNS_CB = ParseAnswerNS;
464                 IO->DNS.Query->QueryTYPE = QT[3];
465                 break;
466
467         case ns_t_txt:
468                 IO->DNS.Query->DNS_CB = ParseAnswerTXT;
469                 IO->DNS.Query->QueryTYPE = QT[4];
470                 break;
471
472         case ns_t_srv:
473                 IO->DNS.Query->DNS_CB = ParseAnswerSRV;
474                 IO->DNS.Query->QueryTYPE = QT[5];
475                 break;
476
477         case ns_t_cname:
478                 IO->DNS.Query->DNS_CB = ParseAnswerCNAME;
479                 IO->DNS.Query->QueryTYPE = QT[6];
480                 break;
481
482         case ns_t_ptr:
483                 IO->DNS.Query->QueryTYPE = QT[7];
484                 if (inet_pton(AF_INET, name, &address_b) == 1) {
485                         length = sizeof(struct in_addr);
486                         family = AF_INET;
487                 } else if (inet_pton(AF_INET6, name, &address_b) == 1) {
488                         length = sizeof(struct in6_addr);
489                         family = AF_INET6;
490                 } else {
491                         return -1;
492                 }
493
494                 ares_gethostbyaddr(IO->DNS.Channel,
495                                    address_b,
496                                    length,
497                                    family,
498                                    HostByAddrCb,
499                                    IO);
500                 EV_DNS_LOGT_START(DNS.timeout);
501                 ev_timer_start(event_base, &IO->DNS.timeout);
502
503                 syslog(LOG_DEBUG, "c-ares: %s X1", __FUNCTION__);
504                 return 1;
505
506         default:
507
508                 syslog(LOG_DEBUG, "c-ares: %sX2", __FUNCTION__);
509                 return 0;
510         }
511         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
512
513         ares_query(IO->DNS.Channel, name, ns_c_in, Type, QueryCb, IO);
514         EV_DNS_LOGT_START(DNS.timeout);
515         ev_timer_start(event_base, &IO->DNS.timeout);
516         return 1;
517 }
518
519
520
521
522
523 /*****************************************************************************
524  *                      libev / c-ares integration                           *
525  *****************************************************************************/
526 static void DNS_send_callback(struct ev_loop *loop, ev_io *watcher, int revents)
527 {
528         AsyncIO *IO = watcher->data;
529
530         IO->Now = ev_now(event_base);
531
532         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
533
534         ares_process_fd(IO->DNS.Channel,
535                         ARES_SOCKET_BAD,
536                         IO->DNS.send_event.fd);
537 }
538 static void DNS_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents)
539 {
540         AsyncIO *IO = watcher->data;
541
542         IO->Now = ev_now(event_base);
543
544         syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__);
545
546         ares_process_fd(IO->DNS.Channel,
547                         IO->DNS.recv_event.fd,
548                         ARES_SOCKET_BAD);
549 }
550
551 void SockStateCb(void *data, int sock, int read, int write)
552 {
553         AsyncIO *IO = data;
554 /* already inside of the event queue. */
555         if (DebugCAres)
556         {
557                 struct sockaddr_in sin;
558                 socklen_t slen;
559                 memset(&sin, 0, sizeof(sin));
560                 slen = sizeof(sin);
561                 if ((IO->DNS.SourcePort == 0) &&
562                     (getsockname(sock, &sin, &slen) == 0))
563                 {
564                         IO->DNS.SourcePort = ntohs(sin.sin_port);
565                 }
566                 syslog(LOG_DEBUG, "c-ares: %s %d|%d Sock %d port %hu", __FUNCTION__, read, write, sock, IO->DNS.SourcePort);
567         }
568
569         IO->Now = ev_now(event_base);
570
571         if (read) {
572                 if ((IO->DNS.recv_event.fd != sock) &&
573                     (IO->DNS.recv_event.fd != 0)) {
574                         EV_DNS_LOG_STOP(DNS.recv_event);
575                         ev_io_stop(event_base, &IO->DNS.recv_event);
576                 }
577                 IO->DNS.recv_event.fd = sock;
578                 ev_io_init(&IO->DNS.recv_event,
579                            DNS_recv_callback,
580                            IO->DNS.recv_event.fd,
581                            EV_READ);
582                 EV_DNS_LOG_INIT(DNS.recv_event);
583                 IO->DNS.recv_event.data = IO;
584                 EV_DNS_LOG_START(DNS.recv_event);
585                 ev_io_start(event_base, &IO->DNS.recv_event);
586         }
587         if (write) {
588                 if ((IO->DNS.send_event.fd != sock) &&
589                     (IO->DNS.send_event.fd != 0)) {
590                         EV_DNS_LOG_STOP(DNS.send_event);
591                         ev_io_stop(event_base, &IO->DNS.send_event);
592                 }
593                 IO->DNS.send_event.fd = sock;
594                 ev_io_init(&IO->DNS.send_event,
595                            DNS_send_callback,
596                            IO->DNS.send_event.fd,
597                            EV_WRITE);
598                 IO->DNS.send_event.data = IO;
599                 EV_DNS_LOG_INIT(DNS.send_event);
600                 EV_DNS_LOG_START(DNS.send_event);
601                 ev_io_start(event_base, &IO->DNS.send_event);
602         }
603         if ((read == 0) && (write == 0)) {
604                 EV_DNS_LOG_STOP(DNS.recv_event);
605                 EV_DNS_LOG_STOP(DNS.send_event);
606                 ev_io_stop(event_base, &IO->DNS.recv_event);
607                 ev_io_stop(event_base, &IO->DNS.send_event);
608         }
609 }
610 void EnableDebugCAres(const int n)
611 {
612         DebugCAres = n;
613 }
614
615 CTDL_MODULE_INIT(c_ares_client)
616 {
617         if (!threading)
618         {
619                 CtdlRegisterDebugFlagHook(HKEY("cares"), EnableDebugCAres, &DebugCAres);
620                 int r = ares_library_init(ARES_LIB_INIT_ALL);
621                 if (0 != r) {
622                         
623                 }
624         }
625         return "c-ares";
626 }