aboutsummaryrefslogtreecommitdiffstats
path: root/resolver.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolver.c')
-rw-r--r--resolver.c457
1 files changed, 0 insertions, 457 deletions
diff --git a/resolver.c b/resolver.c
deleted file mode 100644
index ce047b24..00000000
--- a/resolver.c
+++ /dev/null
@@ -1,457 +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 <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);
-
-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->sa_len, 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.ss_len);
- if (ai->ai_addr == NULL) {
- log_warn("%s: malloc", __func__);
- free(ai);
- break;
- }
-
- memmove(ai->ai_addr, &ss, ss.ss_len);
-
- 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)
- 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);