X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fc-ares-dns%2Fserv_c-ares-dns.c;fp=citadel%2Fmodules%2Fc-ares-dns%2Fserv_c-ares-dns.c;h=0000000000000000000000000000000000000000;hb=5c39ca8a3c875df98163fed8923c258f21bb3f66;hp=06f594bf1a6590bc5d696bdf0eea9302a59d0d22;hpb=45b28b8b70fff7516b7ad33b21a0c2401a0e7201;p=citadel.git diff --git a/citadel/modules/c-ares-dns/serv_c-ares-dns.c b/citadel/modules/c-ares-dns/serv_c-ares-dns.c deleted file mode 100644 index 06f594bf1..000000000 --- a/citadel/modules/c-ares-dns/serv_c-ares-dns.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright (c) 1998-2017 by the citadel.org team - * - * This program is open source software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Inspired by NodeJS.org; thanks for the MX-Parser ;-) - */ - -#include "sysdep.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include "citadel.h" -#include "server.h" -#include "citserver.h" -#include "support.h" - -#include "ctdl_module.h" -#include "event_client.h" - -int DebugCAres = 0; - -extern struct ev_loop *event_base; - -void SockStateCb(void *data, int sock, int read, int write); - - -static void HostByAddrCb(void *data, - int status, - int timeouts, - struct hostent *hostent) -{ - AsyncIO *IO = data; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - EV_DNS_LOGT_STOP(DNS.timeout); - ev_timer_stop (event_base, &IO->DNS.timeout); - - IO->DNS.Query->DNSStatus = status; - if (status != ARES_SUCCESS) { - StrBufPlain(IO->ErrMsg, ares_strerror(status), -1); - return; - } - IO->DNS.Query->Data = hostent; -} - -static void ParseAnswerA(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct hostent* host = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_a_reply(abuf, - alen, - &host, - NULL, - NULL); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (host != NULL) - ares_free_hostent(host); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - IO->DNS.Query->VParsedDNSReply = host; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent; -} - - -static void ParseAnswerAAAA(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct hostent* host = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_aaaa_reply(abuf, - alen, - &host, - NULL, - NULL); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (host != NULL) - ares_free_hostent(host); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - IO->DNS.Query->VParsedDNSReply = host; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent; -} - - -static void ParseAnswerCNAME(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct hostent* host = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_a_reply(abuf, - alen, - &host, - NULL, - NULL); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (host != NULL) - ares_free_hostent(host); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - - // a CNAME lookup always returns a single record but - IO->DNS.Query->VParsedDNSReply = host; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent; -} - - -static void ParseAnswerMX(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct ares_mx_reply *mx_out = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_mx_reply(abuf, alen, &mx_out); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (mx_out != NULL) - ares_free_data(mx_out); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - - IO->DNS.Query->VParsedDNSReply = mx_out; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data; -} - - -static void ParseAnswerNS(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct hostent* host = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_ns_reply(abuf, alen, &host); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (host != NULL) - ares_free_hostent(host); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - IO->DNS.Query->VParsedDNSReply = host; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent; -} - - -static void ParseAnswerSRV(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct ares_srv_reply *srv_out = NULL; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_srv_reply(abuf, alen, &srv_out); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (srv_out != NULL) - ares_free_data(srv_out); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - - IO->DNS.Query->VParsedDNSReply = srv_out; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data; -} - - -static void ParseAnswerTXT(AsyncIO *IO, unsigned char* abuf, int alen) -{ - struct ares_txt_reply *txt_out; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - if (IO->DNS.Query->VParsedDNSReply != NULL) - IO->DNS.Query->DNSReplyFree(IO->DNS.Query->VParsedDNSReply); - IO->DNS.Query->VParsedDNSReply = NULL; - - IO->DNS.Query->DNSStatus = ares_parse_txt_reply(abuf, alen, &txt_out); - if (IO->DNS.Query->DNSStatus != ARES_SUCCESS) { - if (txt_out != NULL) - ares_free_data(txt_out); - StrBufPlain(IO->ErrMsg, - ares_strerror(IO->DNS.Query->DNSStatus), -1); - return; - } - IO->DNS.Query->VParsedDNSReply = txt_out; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_data; -} - -void QueryCb(void *arg, - int status, - int timeouts, - unsigned char* abuf, - int alen) -{ - AsyncIO *IO = arg; - - SetEVState(IO, eCaresStart); - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - EV_DNS_LOGT_STOP(DNS.timeout); - ev_timer_stop (event_base, &IO->DNS.timeout); - - IO->DNS.Query->DNSStatus = status; - if (status == ARES_SUCCESS) - IO->DNS.Query->DNS_CB(arg, abuf, alen); - else { - syslog(LOG_DEBUG, "c-ares: Failed by: %s error %s", __FUNCTION__, ares_strerror(status)); - StrBufPrintf(IO->ErrMsg, - "%s-lookup %s - %s", - IO->DNS.Query->QueryTYPE, - (IO->DNS.Query->QStr != NULL)? IO->DNS.Query->QStr : "", - ares_strerror(status)); - IO->DNS.Query->DNSStatus = status; - } - - ev_idle_init(&IO->unwind_stack, - IO_postdns_callback); - IO->unwind_stack.data = IO; - EV_DNS_LOGT_INIT(unwind_stack); - EV_DNS_LOGT_START(unwind_stack); - ev_idle_start(event_base, &IO->unwind_stack); -} - -void QueryCbDone(AsyncIO *IO) -{ - SetEVState(IO, eCaresDoneIO); - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - EV_DNS_LOGT_STOP(DNS.timeout); - ev_timer_stop (event_base, &IO->DNS.timeout); - - EV_DNS_LOGT_STOP(unwind_stack); - ev_idle_stop(event_base, &IO->unwind_stack); -} - -void DestructCAres(AsyncIO *IO) -{ - SetEVState(IO, eCaresX); - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - syslog(LOG_DEBUG, "c-ares: stopping %s %d %p", "DNS.recv_event", IO->DNS.recv_event.fd, &IO->DNS.recv_event); - ev_io_stop(event_base, &IO->DNS.recv_event); - syslog(LOG_DEBUG, "c-ares: stopping %s %d %p", "DNS.send_event", IO->DNS.send_event.fd, &IO->DNS.send_event); - ev_io_stop(event_base, &IO->DNS.send_event); - syslog(LOG_DEBUG, "c-ares: stopping %s %p", "DNS.timeout", &IO->DNS.send_event); - ev_timer_stop (event_base, &IO->DNS.timeout); - syslog(LOG_DEBUG, "c-ares: stopping %s %p", "DNS.unwind_stack", &IO->unwind_stack); - ev_idle_stop(event_base, &IO->unwind_stack); - ares_destroy_options(&IO->DNS.Options); -} - - -void InitC_ares_dns(AsyncIO *IO) -{ - int optmask = 0; - - syslog(LOG_DEBUG, "c-ares: %s %p", __FUNCTION__, IO->DNS.Channel); - - if (IO->DNS.Channel == NULL) { - optmask |= ARES_OPT_SOCK_STATE_CB; - IO->DNS.Options.sock_state_cb = SockStateCb; - IO->DNS.Options.sock_state_cb_data = IO; - ares_init_options(&IO->DNS.Channel, &IO->DNS.Options, optmask); - } - IO->DNS.Query->DNSStatus = 0; -} - -static void -DNStimeouttrigger_callback(struct ev_loop *loop, ev_timer *watcher, int revents) -{ - AsyncIO *IO = watcher->data; - struct timeval tv, MaxTV; - struct timeval *NextTV; - - memset(&MaxTV, 0, sizeof(MaxTV)); - memset(&tv, 0, sizeof(tv)); - MaxTV.tv_sec = 30; - NextTV = ares_timeout(IO->DNS.Channel, &MaxTV, &tv); - - if ((NextTV->tv_sec != MaxTV.tv_sec) || - (NextTV->tv_usec != MaxTV.tv_usec)) - { - fd_set readers, writers; - syslog(LOG_DEBUG, "c-ares: %s Timeout!", __FUNCTION__); - - FD_ZERO(&readers); - FD_ZERO(&writers); - ares_fds(IO->DNS.Channel, &readers, &writers); - ares_process(IO->DNS.Channel, &readers, &writers); - } -} - -void QueueGetHostByNameDone(void *Ctx, - int status, - int timeouts, - struct hostent *hostent) -{ - AsyncIO *IO = (AsyncIO *) Ctx; - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - - IO->DNS.Query->DNSStatus = status; - IO->DNS.Query->VParsedDNSReply = hostent; - IO->DNS.Query->DNSReplyFree = (FreeDNSReply) ares_free_hostent; - - EV_DNS_LOGT_STOP(DNS.timeout); - ev_timer_stop (event_base, &IO->DNS.timeout); - - ev_idle_init(&IO->unwind_stack, - IO_postdns_callback); - IO->unwind_stack.data = IO; - EV_DNS_LOGT_INIT(unwind_stack); - EV_DNS_LOGT_START(unwind_stack); - ev_idle_start(event_base, &IO->unwind_stack); - -} - -void QueueGetHostByName(AsyncIO *IO, - const char *Hostname, - DNSQueryParts *QueryParts, - IO_CallBack PostDNS) -{ - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - IO->DNS.SourcePort = 0; - - IO->DNS.Query = QueryParts; - IO->DNS.Query->PostDNS = PostDNS; - - InitC_ares_dns(IO); - - ev_timer_init(&IO->DNS.timeout, DNStimeouttrigger_callback, 10, 1); - EV_DNS_LOGT_INIT(DNS.timeout); - IO->DNS.timeout.data = IO; - ares_gethostbyname(IO->DNS.Channel, - Hostname, - AF_INET6, /* it falls back to ipv4 in doubt... */ - QueueGetHostByNameDone, - IO); - EV_DNS_LOGT_START(DNS.timeout); - ev_timer_start(event_base, &IO->DNS.timeout); - -} - -const char* QT[] = { - "A", - "AAAA", - "MX", - "NS", - "TXT", - "SRV", - "CNAME", - "PTR" -}; - -int QueueQuery(ns_type Type, - const char *name, - AsyncIO *IO, - DNSQueryParts *QueryParts, - IO_CallBack PostDNS) -{ - int length, family; - char address_b[sizeof(struct in6_addr)]; - - IO->DNS.SourcePort = 0; - - IO->DNS.Query = QueryParts; - IO->DNS.Query->PostDNS = PostDNS; - IO->DNS.Start = IO->Now; - IO->DNS.Query->QStr = name; - - InitC_ares_dns(IO); - - ev_timer_init(&IO->DNS.timeout, DNStimeouttrigger_callback, 10, 1); - IO->DNS.timeout.data = IO; - EV_DNS_LOGT_INIT(DNS.timeout); - - switch(Type) { - case ns_t_a: - IO->DNS.Query->DNS_CB = ParseAnswerA; - IO->DNS.Query->QueryTYPE = QT[0]; - break; - - case ns_t_aaaa: - IO->DNS.Query->DNS_CB = ParseAnswerAAAA; - IO->DNS.Query->QueryTYPE = QT[1]; - break; - - case ns_t_mx: - IO->DNS.Query->DNS_CB = ParseAnswerMX; - IO->DNS.Query->QueryTYPE = QT[2]; - break; - - case ns_t_ns: - IO->DNS.Query->DNS_CB = ParseAnswerNS; - IO->DNS.Query->QueryTYPE = QT[3]; - break; - - case ns_t_txt: - IO->DNS.Query->DNS_CB = ParseAnswerTXT; - IO->DNS.Query->QueryTYPE = QT[4]; - break; - - case ns_t_srv: - IO->DNS.Query->DNS_CB = ParseAnswerSRV; - IO->DNS.Query->QueryTYPE = QT[5]; - break; - - case ns_t_cname: - IO->DNS.Query->DNS_CB = ParseAnswerCNAME; - IO->DNS.Query->QueryTYPE = QT[6]; - break; - - case ns_t_ptr: - IO->DNS.Query->QueryTYPE = QT[7]; - if (inet_pton(AF_INET, name, &address_b) == 1) { - length = sizeof(struct in_addr); - family = AF_INET; - } else if (inet_pton(AF_INET6, name, &address_b) == 1) { - length = sizeof(struct in6_addr); - family = AF_INET6; - } else { - return -1; - } - - ares_gethostbyaddr(IO->DNS.Channel, - address_b, - length, - family, - HostByAddrCb, - IO); - EV_DNS_LOGT_START(DNS.timeout); - ev_timer_start(event_base, &IO->DNS.timeout); - - syslog(LOG_DEBUG, "c-ares: %s X1", __FUNCTION__); - return 1; - - default: - - syslog(LOG_DEBUG, "c-ares: %sX2", __FUNCTION__); - return 0; - } - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - ares_query(IO->DNS.Channel, name, ns_c_in, Type, QueryCb, IO); - EV_DNS_LOGT_START(DNS.timeout); - ev_timer_start(event_base, &IO->DNS.timeout); - return 1; -} - - - - - -/***************************************************************************** - * libev / c-ares integration * - *****************************************************************************/ -static void DNS_send_callback(struct ev_loop *loop, ev_io *watcher, int revents) -{ - AsyncIO *IO = watcher->data; - - IO->Now = ev_now(event_base); - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - ares_process_fd(IO->DNS.Channel, - ARES_SOCKET_BAD, - IO->DNS.send_event.fd); -} -static void DNS_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents) -{ - AsyncIO *IO = watcher->data; - - IO->Now = ev_now(event_base); - - syslog(LOG_DEBUG, "c-ares: %s", __FUNCTION__); - - ares_process_fd(IO->DNS.Channel, - IO->DNS.recv_event.fd, - ARES_SOCKET_BAD); -} - -void SockStateCb(void *data, int sock, int read, int write) -{ - AsyncIO *IO = data; -/* already inside of the event queue. */ - if (DebugCAres) - { - struct sockaddr_in sin; - socklen_t slen; - memset(&sin, 0, sizeof(sin)); - slen = sizeof(sin); - if ((IO->DNS.SourcePort == 0) && - (getsockname(sock, &sin, &slen) == 0)) - { - IO->DNS.SourcePort = ntohs(sin.sin_port); - } - syslog(LOG_DEBUG, "c-ares: %s %d|%d Sock %d port %hu", __FUNCTION__, read, write, sock, IO->DNS.SourcePort); - } - - IO->Now = ev_now(event_base); - - if (read) { - if ((IO->DNS.recv_event.fd != sock) && - (IO->DNS.recv_event.fd != 0)) { - EV_DNS_LOG_STOP(DNS.recv_event); - ev_io_stop(event_base, &IO->DNS.recv_event); - } - IO->DNS.recv_event.fd = sock; - ev_io_init(&IO->DNS.recv_event, - DNS_recv_callback, - IO->DNS.recv_event.fd, - EV_READ); - EV_DNS_LOG_INIT(DNS.recv_event); - IO->DNS.recv_event.data = IO; - EV_DNS_LOG_START(DNS.recv_event); - ev_io_start(event_base, &IO->DNS.recv_event); - } - if (write) { - if ((IO->DNS.send_event.fd != sock) && - (IO->DNS.send_event.fd != 0)) { - EV_DNS_LOG_STOP(DNS.send_event); - ev_io_stop(event_base, &IO->DNS.send_event); - } - IO->DNS.send_event.fd = sock; - ev_io_init(&IO->DNS.send_event, - DNS_send_callback, - IO->DNS.send_event.fd, - EV_WRITE); - IO->DNS.send_event.data = IO; - EV_DNS_LOG_INIT(DNS.send_event); - EV_DNS_LOG_START(DNS.send_event); - ev_io_start(event_base, &IO->DNS.send_event); - } - if ((read == 0) && (write == 0)) { - EV_DNS_LOG_STOP(DNS.recv_event); - EV_DNS_LOG_STOP(DNS.send_event); - ev_io_stop(event_base, &IO->DNS.recv_event); - ev_io_stop(event_base, &IO->DNS.send_event); - } -} -void EnableDebugCAres(const int n) -{ - DebugCAres = n; -} - -CTDL_MODULE_INIT(c_ares_client) -{ - if (!threading) - { - CtdlRegisterDebugFlagHook(HKEY("cares"), EnableDebugCAres, &DebugCAres); - int r = ares_library_init(ARES_LIB_INIT_ALL); - if (0 != r) { - - } - } - return "c-ares"; -}