Changeset b4049f9 in code for dns.c


Ignore:
Timestamp:
Mar 4, 2014, 10:34:57 AM (11 years ago)
Author:
Mike Belopuhov <mike@…>
Branches:
master
Children:
5815eef
Parents:
fa271b8
Message:

Rewrite DNS resolver to do things truly asynchronously

File:
1 edited

Legend:

Unmodified
Added
Removed
  • dns.c

    rfa271b8 rb4049f9  
    11/*
     2 * Copyright (c) 2013 Mike Belopuhov
    23 * Copyright (c) 2009 Michael Shalayeff
    34 * All rights reserved.
     
    2324#include <errno.h>
    2425#include <stdlib.h>
     26#include <string.h>
    2527#include <unistd.h>
    2628#include <syslog.h>
     
    3537
    3638void dns_dispatch(int, short, void *);
     39void dns_done(int, short, void *);
    3740int dns_pipe;
    3841
     42
     43struct icbd_dnsquery {
     44        uint64_t                        sid;
     45        union {
     46                struct sockaddr_storage req;
     47                char                    rep[MAXHOSTNAMELEN];
     48        } u;
     49};
     50
    3951int
    40 icbd_dns_init(void)
     52dns_init(void)
    4153{
    42         struct event    ev;
    43         int             pipe[2];
    44         struct passwd   *pw;
     54        static struct event ev;
     55        struct passwd *pw;
     56        int pipes[2];
    4557
    46         if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe) == -1) {
     58        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipes) == -1) {
    4759                syslog(LOG_ERR, "socketpair: %m");
    4860                exit(EX_OSERR);
     
    5769
    5870        default:
    59                 close(pipe[1]);
    60                 dns_pipe = pipe[0];
     71                close(pipes[1]);
     72                dns_pipe = pipes[0];
     73
     74                /* event for the reply */
     75                event_set(&ev, dns_pipe, EV_READ | EV_PERSIST,
     76                    dns_done, NULL);
     77                if (event_add(&ev, NULL) < 0) {
     78                        syslog(LOG_ERR, "event_add: %m");
     79                        exit (EX_UNAVAILABLE);
     80                }
    6181                return (0);
    6282        }
    6383
    6484        setproctitle("dns resolver");
    65         close(pipe[0]);
     85        close(pipes[0]);
    6686
    6787        if ((pw = getpwnam(ICBD_USER)) == NULL) {
     
    86106        event_init();
    87107
    88         event_set(&ev, pipe[1], EV_READ | EV_PERSIST, dns_dispatch, NULL);
     108        /* event for the request */
     109        event_set(&ev, pipes[1], EV_READ | EV_PERSIST, dns_dispatch, NULL);
    89110        if (event_add(&ev, NULL) < 0) {
    90111                syslog(LOG_ERR, "event_add: %m");
     
    96117
    97118void
    98 dns_dispatch(int fd, short event, void *arg)
     119dns_dispatch(int fd, short event, void *arg __attribute__((unused)))
    99120{
    100121        char host[NI_MAXHOST];
    101         struct sockaddr_storage ss;
    102         struct sockaddr *sa = (struct sockaddr *)&ss;
    103         int gerr, ss_len = sizeof ss;
     122        struct sockaddr *sa;
     123        struct icbd_dnsquery q;
     124        int gerr;
    104125
    105126        arg = NULL;
     
    107128                return;
    108129
    109         if (read(fd, &ss, ss_len) != ss_len) {
     130        if (read(fd, &q, sizeof q) != sizeof q) {
    110131                syslog(LOG_ERR, "dns read: %m");
    111132                exit(1);
    112133        }
    113134
     135        sa = (struct sockaddr *)&q.u.req;
    114136        if ((gerr = getnameinfo(sa, sa->sa_len,
    115137            host, sizeof host, NULL, 0, NI_NOFQDN))) {
    116138                syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(gerr));
    117                 write(fd, host, sizeof host);
    118139                return;
    119140        }
     
    122143                syslog(LOG_DEBUG, "dns_dispatch: resolved %s", host);
    123144
    124         if (write(fd, host, sizeof host) != sizeof host)
     145        memcpy(&q.u.rep, host, sizeof host);
     146        if (write(fd, &q, sizeof q) != sizeof q)
    125147                syslog(LOG_ERR, "dns write: %m");
     148}
     149
     150void
     151dns_done(int fd, short event, void *arg __attribute__((unused)))
     152{
     153        struct icb_session *is;
     154        struct icbd_dnsquery q;
     155
     156        if (event != EV_READ)
     157                return;
     158
     159        if (read(fd, &q, sizeof q) != sizeof q) {
     160                syslog(LOG_ERR, "read: %m");
     161                return;
     162        }
     163
     164        if ((is = icbd_session_lookup(q.sid)) == NULL) {
     165                syslog(LOG_ERR, "failed to find session %llu", q.sid);
     166                return;
     167        }
     168
     169        memcpy(is->host, q.u.rep, MAXHOSTNAMELEN);
     170        is->host[sizeof is->host - 1] = '\0';
     171
     172        if (verbose)
     173                syslog(LOG_DEBUG, "icbd_dns: resolved %s", is->host);
    126174}
    127175
     
    129177dns_rresolv(struct icb_session *is, struct sockaddr_storage *ss)
    130178{
    131         /* one-shot event for the reply */
    132         event_set(&is->ev, dns_pipe, EV_READ, icbd_dns, is);
    133         if (event_add(&is->ev, NULL) < 0) {
    134                 syslog(LOG_ERR, "event_add: %m");
    135                 exit (EX_UNAVAILABLE);
    136         }
    137 
    138         inet_ntop(ss->ss_family, ss->ss_family == AF_INET ?
    139             (void *)&((struct sockaddr_in *)ss)->sin_addr :
    140             (void *)&((struct sockaddr_in6 *)ss)->sin6_addr,
    141             is->host, sizeof is->host);
     179        struct icbd_dnsquery q;
    142180
    143181        if (verbose)
    144182                syslog(LOG_DEBUG, "resolving: %s", is->host);
    145183
    146         if (write(dns_pipe, ss, sizeof *ss) != sizeof *ss) {
     184        memset(&q, 0, sizeof q);
     185        q.sid = is->id;
     186        memcpy(&q.u.req, ss, sizeof *ss);
     187        if (write(dns_pipe, &q, sizeof q) != sizeof q) {
    147188                syslog(LOG_ERR, "write: %m");
    148189                exit (EX_OSERR);
Note: See TracChangeset for help on using the changeset viewer.