+++ /dev/null
-/* -*-c-*-
- *
- * Background reverse name resolution (ADNS version)
- *
- * (c) 2003 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of the mLib utilities library.
- *
- * mLib is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * mLib 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with mLib; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- *
- * HOWEVER, since GNU adns is covered by the full GNU General Public
- * License, this file (only) is also covered by the full GNU GPL, and
- * you may NOT take advantage of the more liberal conditions of the
- * LGPL when modifying or redistributing this file. This doesn't mean
- * that a program which uses the interface provided by this file is
- * covered by the GPL, since @bres.c@ provides the same interface and
- * is LGPL. However, it does mean that if your program depends, for
- * some reason (e.g., to meet particular performance criteria), on
- * this adns-based implementation of mLib's background resolver then it
- * must be licensed under the full GPL.
- */
-
-#include "config.h"
-
-#ifndef HAVE_ADNS
-# error "You need the ADNS library to compile this file."
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <sys/wait.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <adns.h>
-
-#include "alloc.h"
-#include "bres.h"
-#include "macros.h"
-#include "report.h"
-#include "sel.h"
-
-/*----- Static variables --------------------------------------------------*/
-
-static adns_state ads;
-static sel_state *sel;
-static sel_hook selhook;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @bres_abort@ --- *
- *
- * Arguments: @bres_client *rc@ = pointer to client block
- *
- * Returns: ---
- *
- * Use: Removes a queued job.
- */
-
-void bres_abort(bres_client *rc)
-{
- if (rc->q == adns_r_addr) xfree(rc->u.name);
- if (rc->a) free(rc->a);
- adns_cancel(rc->aq);
-}
-
-/* --- @bres_byaddr@ --- *
- *
- * Arguments: @bres_client *rc@ = pointer to client block
- * @struct in_addr addr@ = address to resolve
- * @void (*func)(struct hostent *h, void *p)@ = handler function
- * @void *p@ = argument for handler function
- *
- * Returns: ---
- *
- * Use: Adds an address lookup job to the queue. The job will be
- * processed when there's a spare resolver process to deal with
- * it.
- */
-
-void bres_byaddr(bres_client *rc, struct in_addr addr,
- void (*func)(struct hostent */*h*/, void */*p*/),
- void *p)
-{
- int e;
- struct sockaddr_in sin;
-
- if (!ads) goto fail;
- sin.sin_family = AF_INET;
- sin.sin_addr = addr;
- sin.sin_port = 0;
- if ((e = adns_submit_reverse(ads, (struct sockaddr *)&sin, adns_r_ptr,
- 0, rc, &rc->aq)) != 0)
- goto fail;
- rc->a = 0;
- rc->q = adns_r_ptr;
- rc->u.addr = addr;
- rc->func = func;
- rc->p = p;
- return;
-
-fail:
- func(0, p);
-}
-
-/* --- @bres_byname@ --- *
- *
- * Arguments: @bres_client *rc@ = pointer to client block
- * @const char *name@ = name to resolve
- * @void (*func)(struct hostent *h, void *p)@ = handler function
- * @void *p@ = argument for handler function
- *
- * Returns: ---
- *
- * Use: Adds a name lookup job to the queue. The job will be
- * processed when there's a spare resolver process to deal with
- * it.
- */
-
-void bres_byname(bres_client *rc, const char *name,
- void (*func)(struct hostent */*h*/, void */*p*/),
- void *p)
-{
- int e;
-
- if (!ads) goto fail;
- if ((e = adns_submit(ads, name, adns_r_addr,
- adns_qf_search | adns_qf_owner, rc, &rc->aq)) != 0)
- goto fail;
- rc->a = 0;
- rc->q = adns_r_addr;
- rc->u.name = xstrdup(name);
- rc->func = func;
- rc->p = p;
- return;
-
-fail:
- func(0, p);
-}
-
-/* --- @bres_exec@ --- *
- *
- * Arguments: @const char *file@ = file containing server code or null
- *
- * Returns: ---
- *
- * Use: Makes `bres' use a standalone server rather than copies of
- * the current process. This can reduce memory consumption for
- * large processes, at the expense of startup time (which
- * shouldn't be too bad anyway, because of the resolver design).
- * If the filename is null, a default set up at install time is
- * used. It's probably a good idea to leave it alone.
- */
-
-void bres_exec(const char *file)
-{
- /* Nothin' doin' */
-}
-
-/* --- @report@ --- *
- *
- * Arguments: @bres_client *c@ = client descriptor block
- * @adns_answer *a@ = A-record answer from resolver library
- * @adns_rr_addr *av@ = vector of address records
- * @int an@ = number of address records (must be positive)
- * @char **nv@ = vector of name strings
- * @int nn@ = number of name strings (must be positive)
- *
- * Returns: ---
- *
- * Use: Formats the given answer into a @struct hostent@ and reports
- * it to the waiting client application.
- */
-
-static void report(bres_client *rc, adns_answer *a,
- adns_rr_addr *av, int an,
- char **nv, int nn)
-{
- struct hostent h;
- char *n[16];
- char *aa[16];
- int i, j;
-
- j = 0;
- if (a->cname) n[j++] = a->cname;
- else { n[j++] = *nv; nv++; nn--; }
- for (i = 0; i < nn && j < N(n) - 1; i++)
- if (strcmp(n[0], nv[i]) != 0) n[j++] = nv[i];
- n[j++] = 0;
- for (i = j = 0; i < an && j < N(av) - 1; i++) {
- if (av[i].addr.sa.sa_family == AF_INET)
- aa[j++] = (char *)&av[i].addr.inet.sin_addr;
- }
- aa[j++] = 0;
- h.h_name = n[0];
- h.h_aliases = n + 1;
- h.h_addrtype = AF_INET;
- h.h_length = sizeof(struct in_addr);
- h.h_addr_list = aa;
- rc->func(&h, rc->p);
-}
-
-/* --- @beforehook@, @afterhook@ --- *
- *
- * Arguments: @sel_state *s@ = select state
- * @sel_args *sa@ = argument block
- * @void *p@ = uninteresting pointer
- *
- * Returns: ---
- *
- * Use: Processes the selector's arguments before @select@ is
- * called, to allow ADNS to do its thing.
- */
-
-static void beforehook(sel_state *s, sel_args *sa, void *p)
-{
- adns_beforeselect(ads, &sa->maxfd,
- &sa->fd[SEL_READ], &sa->fd[SEL_WRITE], &sa->fd[SEL_EXC],
- &sa->tvp, &sa->tv, &sa->now);
-}
-
-static void afterhook(sel_state *s, sel_args *sa, void *p)
-{
- void *c;
- bres_client *rc;
- adns_query q;
- adns_answer *a, *aa;
- int e;
- int i;
-
- adns_afterselect(ads, sa->maxfd,
- &sa->fd[SEL_READ], &sa->fd[SEL_WRITE], &sa->fd[SEL_EXC],
- &sa->now);
- while (q = 0, (e = adns_check(ads, &q, &a, &c)) == 0) {
- rc = c;
- if (a->status != 0)
- goto fail;
- else switch (rc->q) {
- case adns_r_addr:
- assert(a->type == adns_r_addr);
- xfree(rc->u.name);
- report(rc, a, a->rrs.addr, a->nrrs, &a->owner, 1);
- free(a);
- break;
- case adns_r_ptr:
- if (a->type == adns_r_ptr) {
- rc->a = a;
- if ((e = adns_submit(ads, a->rrs.str[0], adns_r_addr,
- 0, rc, &q)) != 0)
- goto fail;
- rc->aq = q;
- } else {
- assert(a->type == adns_r_addr);
- for (i = 0; i < a->nrrs; i++) {
- if (a->rrs.addr[i].addr.sa.sa_family == AF_INET &&
- a->rrs.addr[i].addr.inet.sin_addr.s_addr ==
- rc->u.addr.s_addr)
- goto match;
- }
- goto fail;
- match:
- aa = rc->a;
- report(rc, a, &a->rrs.addr[i], 1, aa->rrs.str, aa->nrrs);
- free(aa);
- free(a);
- }
- break;
- default:
- abort();
- }
- continue;
-
- fail:
- if (rc->q == adns_r_addr) xfree(rc->u.name);
- if (rc->a) free(rc->a);
- rc->func(0, rc->p);
- free(a);
- }
-}
-
-/* --- @bres_init@ --- *
- *
- * Arguments: @sel_state *s@ = pointer to select multiplexor
- *
- * Returns: ---
- *
- * Use: Initializes the background resolver for use.
- */
-
-void bres_init(sel_state *s)
-{
- int e;
-
- if ((e = adns_init(&ads, adns_if_noautosys, 0)) != 0) {
- moan("adns_init failed: resolver won't work");
- return;
- }
- sel_addhook(s, &selhook, beforehook, afterhook, 0);
- sel = s;
-}
-
-/*----- That's all, folks -------------------------------------------------*/