diff options
Diffstat (limited to 'smtpd/resolver.c')
-rw-r--r-- | smtpd/resolver.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/smtpd/resolver.c b/smtpd/resolver.c deleted file mode 100644 index f0f0f8ea..00000000 --- a/smtpd/resolver.c +++ /dev/null @@ -1,462 +0,0 @@ -/* $OpenBSD: resolver.c,v 1.5 2019/06/13 11:45:35 eric Exp $ */ - -/* - * Copyright (c) 2017-2018 Eric Faurot <eric@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/tree.h> -#include <sys/queue.h> -#include <netinet/in.h> - -#include <asr.h> -#include <ctype.h> -#include <errno.h> -#include <imsg.h> -#include <limits.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "smtpd.h" -#include "log.h" - -#define p_resolver p_lka - -struct request { - SPLAY_ENTRY(request) entry; - uint32_t id; - void (*cb_ai)(void *, int, struct addrinfo *); - void (*cb_ni)(void *, int, const char *, const char *); - void (*cb_res)(void *, int, int, int, const void *, int); - void *arg; - struct addrinfo *ai; -}; - -struct session { - uint32_t reqid; - struct mproc *proc; - char *host; - char *serv; -}; - -SPLAY_HEAD(reqtree, request); - -static void resolver_init(void); -static void resolver_getaddrinfo_cb(struct asr_result *, void *); -static void resolver_getnameinfo_cb(struct asr_result *, void *); -static void resolver_res_query_cb(struct asr_result *, void *); - -static int request_cmp(struct request *, struct request *); -SPLAY_PROTOTYPE(reqtree, request, entry, request_cmp); - -/* musl work-around */ -void portable_freeaddrinfo(struct addrinfo *); - -static struct reqtree reqs; - -void -resolver_getaddrinfo(const char *hostname, const char *servname, - const struct addrinfo *hints, void (*cb)(void *, int, struct addrinfo *), - void *arg) -{ - struct request *req; - - resolver_init(); - - req = calloc(1, sizeof(*req)); - if (req == NULL) { - cb(arg, EAI_MEMORY, NULL); - return; - } - - while (req->id == 0 || SPLAY_FIND(reqtree, &reqs, req)) - req->id = arc4random(); - req->cb_ai = cb; - req->arg = arg; - - SPLAY_INSERT(reqtree, &reqs, req); - - m_create(p_resolver, IMSG_GETADDRINFO, req->id, 0, -1); - m_add_int(p_resolver, hints ? hints->ai_flags : 0); - m_add_int(p_resolver, hints ? hints->ai_family : 0); - m_add_int(p_resolver, hints ? hints->ai_socktype : 0); - m_add_int(p_resolver, hints ? hints->ai_protocol : 0); - m_add_string(p_resolver, hostname); - m_add_string(p_resolver, servname); - m_close(p_resolver); -} - -void -resolver_getnameinfo(const struct sockaddr *sa, int flags, - void(*cb)(void *, int, const char *, const char *), void *arg) -{ - struct request *req; - - resolver_init(); - - req = calloc(1, sizeof(*req)); - if (req == NULL) { - cb(arg, EAI_MEMORY, NULL, NULL); - return; - } - - while (req->id == 0 || SPLAY_FIND(reqtree, &reqs, req)) - req->id = arc4random(); - req->cb_ni = cb; - req->arg = arg; - - SPLAY_INSERT(reqtree, &reqs, req); - - m_create(p_resolver, IMSG_GETNAMEINFO, req->id, 0, -1); - m_add_sockaddr(p_resolver, sa); - m_add_int(p_resolver, flags); - m_close(p_resolver); -} - -void -resolver_res_query(const char *dname, int class, int type, - void (*cb)(void *, int, int, int, const void *, int), void *arg) -{ - struct request *req; - - resolver_init(); - - req = calloc(1, sizeof(*req)); - if (req == NULL) { - cb(arg, NETDB_INTERNAL, 0, 0, NULL, 0); - return; - } - - while (req->id == 0 || SPLAY_FIND(reqtree, &reqs, req)) - req->id = arc4random(); - req->cb_res = cb; - req->arg = arg; - - SPLAY_INSERT(reqtree, &reqs, req); - - m_create(p_resolver, IMSG_RES_QUERY, req->id, 0, -1); - m_add_string(p_resolver, dname); - m_add_int(p_resolver, class); - m_add_int(p_resolver, type); - m_close(p_resolver); -} - -void -resolver_dispatch_request(struct mproc *proc, struct imsg *imsg) -{ - const char *hostname, *servname, *dname; - struct session *s; - struct asr_query *q; - struct addrinfo hints; - struct sockaddr_storage ss; - struct sockaddr *sa; - struct msg m; - uint32_t reqid; - int class, type, flags, save_errno; - - reqid = imsg->hdr.peerid; - m_msg(&m, imsg); - - switch (imsg->hdr.type) { - - case IMSG_GETADDRINFO: - servname = NULL; - memset(&hints, 0 , sizeof(hints)); - m_get_int(&m, &hints.ai_flags); - m_get_int(&m, &hints.ai_family); - m_get_int(&m, &hints.ai_socktype); - m_get_int(&m, &hints.ai_protocol); - m_get_string(&m, &hostname); - m_get_string(&m, &servname); - m_end(&m); - - s = NULL; - q = NULL; - if ((s = calloc(1, sizeof(*s))) && - (q = getaddrinfo_async(hostname, servname, &hints, NULL)) && - (event_asr_run(q, resolver_getaddrinfo_cb, s))) { - s->reqid = reqid; - s->proc = proc; - break; - } - save_errno = errno; - - if (q) - asr_abort(q); - if (s) - free(s); - - m_create(proc, IMSG_GETADDRINFO_END, reqid, 0, -1); - m_add_int(proc, EAI_SYSTEM); - m_add_int(proc, save_errno); - m_close(proc); - break; - - case IMSG_GETNAMEINFO: - sa = (struct sockaddr*)&ss; - m_get_sockaddr(&m, sa); - m_get_int(&m, &flags); - m_end(&m); - - s = NULL; - q = NULL; - if ((s = calloc(1, sizeof(*s))) && - (s->host = malloc(NI_MAXHOST)) && - (s->serv = malloc(NI_MAXSERV)) && - (q = getnameinfo_async(sa, SA_LEN(sa), s->host, NI_MAXHOST, - s->serv, NI_MAXSERV, flags, NULL)) && - (event_asr_run(q, resolver_getnameinfo_cb, s))) { - s->reqid = reqid; - s->proc = proc; - break; - } - save_errno = errno; - - if (q) - asr_abort(q); - if (s) { - free(s->host); - free(s->serv); - free(s); - } - - m_create(proc, IMSG_GETNAMEINFO, reqid, 0, -1); - m_add_int(proc, EAI_SYSTEM); - m_add_int(proc, save_errno); - m_add_string(proc, NULL); - m_add_string(proc, NULL); - m_close(proc); - break; - - case IMSG_RES_QUERY: - m_get_string(&m, &dname); - m_get_int(&m, &class); - m_get_int(&m, &type); - m_end(&m); - - s = NULL; - q = NULL; - if ((s = calloc(1, sizeof(*s))) && - (q = res_query_async(dname, class, type, NULL)) && - (event_asr_run(q, resolver_res_query_cb, s))) { - s->reqid = reqid; - s->proc = proc; - break; - } - save_errno = errno; - - if (q) - asr_abort(q); - if (s) - free(s); - - m_create(proc, IMSG_RES_QUERY, reqid, 0, -1); - m_add_int(proc, NETDB_INTERNAL); - m_add_int(proc, save_errno); - m_add_int(proc, 0); - m_add_int(proc, 0); - m_add_data(proc, NULL, 0); - m_close(proc); - break; - - default: - fatalx("%s: %s", __func__, imsg_to_str(imsg->hdr.type)); - } -} - -void -resolver_dispatch_result(struct mproc *proc, struct imsg *imsg) -{ - struct request key, *req; - struct sockaddr_storage ss; - struct addrinfo *ai; - struct msg m; - const char *cname, *host, *serv; - const void *data; - size_t datalen; - int gai_errno, herrno, rcode, count; - - key.id = imsg->hdr.peerid; - req = SPLAY_FIND(reqtree, &reqs, &key); - if (req == NULL) - fatalx("%s: unknown request %08x", __func__, imsg->hdr.peerid); - - m_msg(&m, imsg); - - switch (imsg->hdr.type) { - - case IMSG_GETADDRINFO: - ai = calloc(1, sizeof(*ai)); - if (ai == NULL) { - log_warn("%s: calloc", __func__); - break; - } - m_get_int(&m, &ai->ai_flags); - m_get_int(&m, &ai->ai_family); - m_get_int(&m, &ai->ai_socktype); - m_get_int(&m, &ai->ai_protocol); - m_get_sockaddr(&m, (struct sockaddr *)&ss); - m_get_string(&m, &cname); - m_end(&m); - - ai->ai_addr = malloc(SS_LEN(&ss)); - if (ai->ai_addr == NULL) { - log_warn("%s: malloc", __func__); - free(ai); - break; - } - - memmove(ai->ai_addr, &ss, SS_LEN(&ss)); - - if (cname) { - ai->ai_canonname = strdup(cname); - if (ai->ai_canonname == NULL) { - log_warn("%s: strdup", __func__); - free(ai->ai_addr); - free(ai); - break; - } - } - - ai->ai_next = req->ai; - req->ai = ai; - break; - - case IMSG_GETADDRINFO_END: - m_get_int(&m, &gai_errno); - m_get_int(&m, &errno); - m_end(&m); - - SPLAY_REMOVE(reqtree, &reqs, req); - req->cb_ai(req->arg, gai_errno, req->ai); - free(req); - break; - - case IMSG_GETNAMEINFO: - m_get_int(&m, &gai_errno); - m_get_int(&m, &errno); - m_get_string(&m, &host); - m_get_string(&m, &serv); - m_end(&m); - - SPLAY_REMOVE(reqtree, &reqs, req); - req->cb_ni(req->arg, gai_errno, host, serv); - free(req); - break; - - case IMSG_RES_QUERY: - m_get_int(&m, &herrno); - m_get_int(&m, &errno); - m_get_int(&m, &rcode); - m_get_int(&m, &count); - m_get_data(&m, &data, &datalen); - m_end(&m); - - SPLAY_REMOVE(reqtree, &reqs, req); - req->cb_res(req->arg, herrno, rcode, count, data, datalen); - free(req); - break; - } -} - -static void -resolver_init(void) -{ - static int init = 0; - - if (init == 0) { - SPLAY_INIT(&reqs); - init = 1; - } -} - -static void -resolver_getaddrinfo_cb(struct asr_result *ar, void *arg) -{ - struct session *s = arg; - struct addrinfo *ai; - - for (ai = ar->ar_addrinfo; ai; ai = ai->ai_next) { - m_create(s->proc, IMSG_GETADDRINFO, s->reqid, 0, -1); - m_add_int(s->proc, ai->ai_flags); - m_add_int(s->proc, ai->ai_family); - m_add_int(s->proc, ai->ai_socktype); - m_add_int(s->proc, ai->ai_protocol); - m_add_sockaddr(s->proc, ai->ai_addr); - m_add_string(s->proc, ai->ai_canonname); - m_close(s->proc); - } - - m_create(s->proc, IMSG_GETADDRINFO_END, s->reqid, 0, -1); - m_add_int(s->proc, ar->ar_gai_errno); - m_add_int(s->proc, ar->ar_errno); - m_close(s->proc); - - if (ar->ar_addrinfo) - portable_freeaddrinfo(ar->ar_addrinfo); - free(s); -} - -static void -resolver_getnameinfo_cb(struct asr_result *ar, void *arg) -{ - struct session *s = arg; - - m_create(s->proc, IMSG_GETNAMEINFO, s->reqid, 0, -1); - m_add_int(s->proc, ar->ar_gai_errno); - m_add_int(s->proc, ar->ar_errno); - m_add_string(s->proc, ar->ar_gai_errno ? NULL : s->host); - m_add_string(s->proc, ar->ar_gai_errno ? NULL : s->serv); - m_close(s->proc); - - free(s->host); - free(s->serv); - free(s); -} - -static void -resolver_res_query_cb(struct asr_result *ar, void *arg) -{ - struct session *s = arg; - - m_create(s->proc, IMSG_RES_QUERY, s->reqid, 0, -1); - m_add_int(s->proc, ar->ar_h_errno); - m_add_int(s->proc, ar->ar_errno); - m_add_int(s->proc, ar->ar_rcode); - m_add_int(s->proc, ar->ar_count); - m_add_data(s->proc, ar->ar_data, ar->ar_datalen); - m_close(s->proc); - - free(ar->ar_data); - free(s); -} - -static int -request_cmp(struct request *a, struct request *b) -{ - if (a->id < b->id) - return -1; - if (a->id > b->id) - return 1; - return 0; -} - -SPLAY_GENERATE(reqtree, request, entry, request_cmp); |