Changeset e87ab6d in code
- Timestamp:
- Mar 9, 2014, 3:09:45 PM (11 years ago)
- Branches:
- master
- Children:
- dcbd425
- Parents:
- 718d0c9
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r718d0c9 re87ab6d 11 11 CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare 12 12 13 # hook up asynchronous resolver 14 CFLAGS+= -I${BSDSRCDIR}/lib/libc/asr 15 13 16 DPADD= ${LIBEVENT} 14 17 LDADD= -levent -
dns.c
r718d0c9 re87ab6d 1 1 /* 2 2 * Copyright (c) 2014 Mike Belopuhov 3 * Copyright (c) 2009 Michael Shalayeff 4 * All rights reserved. 3 * 4 * ASR implementation and OpenSMTPD integration are copyright 5 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> 6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * Copyright (c) 2011-2012 Eric Faurot <eric@faurot.net> 5 8 * 6 9 * Permission to use, copy, modify, and distribute this software for any … … 17 20 */ 18 21 19 #include <sys/ param.h>22 #include <sys/types.h> 20 23 #include <sys/socket.h> 21 24 #include <sys/time.h> 22 25 #include <netinet/in.h> 23 #include <arpa/inet.h>24 26 #include <errno.h> 27 #include <event.h> 28 #include <resolv.h> 25 29 #include <stdlib.h> 26 30 #include <string.h> 27 #include <unistd.h>28 31 #include <syslog.h> 29 #include <sysexits.h> 30 #include <login_cap.h> 31 #include <event.h> 32 #include <pwd.h> 33 #include <netdb.h> 32 33 #include "asr.h" 34 34 35 35 #include "icb.h" 36 36 #include "icbd.h" 37 37 38 void dns_dispatch(int, short, void *); 39 void dns_done(int, short, void *); 40 41 struct icbd_dnsquery { 42 uint64_t sid; 43 union { 44 struct sockaddr_storage req; 45 char rep[NI_MAXHOST]; 46 } u; 47 }; 48 49 int dns_pipe; 38 struct async_event; 39 struct async_event * 40 async_run_event(struct async *, 41 void (*)(int, struct async_res *, void *), void *); 42 void dns_done(int, struct async_res *, void *); 50 43 51 44 extern int dodns; 52 45 53 int 54 dns_ init(void)46 void 47 dns_done(int ev __attribute__((__unused__)), struct async_res *ar, void *arg) 55 48 { 56 static struct event ev; 57 struct passwd *pw; 58 int pipes[2]; 49 struct icb_session *is = arg; 59 50 60 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipes) == -1) { 61 syslog(LOG_ERR, "socketpair: %m"); 62 exit(EX_OSERR); 63 } 64 65 switch (fork()) { 66 case -1: 67 syslog(LOG_ERR, "fork: %m"); 68 exit(EX_OSERR); 69 case 0: 70 break; 71 72 default: 73 close(pipes[1]); 74 dns_pipe = pipes[0]; 75 76 /* event for the reply */ 77 event_set(&ev, dns_pipe, EV_READ | EV_PERSIST, 78 dns_done, NULL); 79 if (event_add(&ev, NULL) < 0) { 80 syslog(LOG_ERR, "event_add: %m"); 81 exit (EX_UNAVAILABLE); 82 } 83 return (0); 84 } 85 86 setproctitle("dns resolver"); 87 close(pipes[0]); 88 89 if ((pw = getpwnam(ICBD_USER)) == NULL) { 90 syslog(LOG_ERR, "No passwd entry for %s", ICBD_USER); 91 exit(EX_NOUSER); 92 } 93 94 if (chdir("/") < 0) { 95 syslog(LOG_ERR, "chdir: %m"); 96 exit(EX_UNAVAILABLE); 97 } 98 99 if (setusercontext(NULL, pw, pw->pw_uid, 100 LOGIN_SETALL & ~LOGIN_SETUSER) < 0) 101 exit(EX_NOPERM); 102 103 if (setuid(pw->pw_uid) < 0) { 104 syslog(LOG_ERR, "%d: %m", pw->pw_uid); 105 exit(EX_NOPERM); 106 } 107 108 event_init(); 109 110 /* event for the request */ 111 event_set(&ev, pipes[1], EV_READ | EV_PERSIST, dns_dispatch, NULL); 112 if (event_add(&ev, NULL) < 0) { 113 syslog(LOG_ERR, "event_add: %m"); 114 exit (EX_UNAVAILABLE); 115 } 116 117 return event_dispatch(); 51 if (ar->ar_gai_errno == 0) { 52 syslog(LOG_DEBUG, "dns resolved %s to %s", is->host, 53 is->hostname); 54 if (strncmp(is->hostname, "localhost", 55 sizeof "localhost" - 1) == 0) 56 strlcpy(is->host, "unknown", ICB_MAXHOSTLEN); 57 else if (strlen(is->hostname) < ICB_MAXHOSTLEN) 58 strlcpy(is->host, is->hostname, ICB_MAXHOSTLEN); 59 } else 60 syslog(LOG_WARNING, "dns resolution failed: %s", 61 gai_strerror(ar->ar_gai_errno)); 118 62 } 119 63 120 64 void 121 dns_ dispatch(int fd, short event, void *arg __attribute__((unused)))65 dns_rresolv(struct icb_session *is, struct sockaddr *sa) 122 66 { 123 char host[NI_MAXHOST]; 124 struct sockaddr *sa; 125 struct icbd_dnsquery q; 126 ssize_t res; 127 int gerr; 128 129 if (event != EV_READ) 130 return; 131 132 do 133 res = read(fd, &q, sizeof q); 134 while (res == -1 && errno == EINTR); 135 if (res == -1 && errno == EAGAIN) 136 return; 137 if (res < (ssize_t)sizeof q) { 138 syslog(LOG_ERR, "dns_dispatch read: %m"); 139 /* disable dns resolver */ 140 dodns = 0; 141 return; 142 } 143 144 sa = (struct sockaddr *)&q.u.req; 145 if ((gerr = getnameinfo(sa, sa->sa_len, 146 host, sizeof host, NULL, 0, NI_NOFQDN))) { 147 syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(gerr)); 148 return; 149 } 150 151 if (verbose) 152 syslog(LOG_DEBUG, "dns_dispatch: resolved %s", host); 153 154 memcpy(&q.u.rep, host, sizeof host); 155 if (write(fd, &q, sizeof q) != sizeof q) 156 syslog(LOG_ERR, "dns_dispatch write: %m"); 157 } 158 159 void 160 dns_done(int fd, short event, void *arg __attribute__((unused))) 161 { 162 struct icb_session *is; 163 struct icbd_dnsquery q; 164 ssize_t res; 165 166 if (event != EV_READ) 167 return; 168 169 do 170 res = read(fd, &q, sizeof q); 171 while (res == -1 && errno == EINTR); 172 if (res == -1 && errno == EAGAIN) 173 return; 174 if (res < (ssize_t)sizeof q) { 175 syslog(LOG_ERR, "dns_done read: %m"); 176 return; 177 } 178 179 if ((is = icbd_session_lookup(q.sid)) == NULL) { 180 syslog(LOG_DEBUG, "failed to find session %llu", q.sid); 181 return; 182 } 183 184 if (verbose) 185 syslog(LOG_DEBUG, "icbd_dns: resolved %s to %s", 186 is->host, q.u.rep); 187 188 /* XXX */ 189 if (strcmp(q.u.rep, "localhost") == 0) 190 strlcpy(is->host, "unknown", ICB_MAXHOSTLEN); 191 else if (strlen(q.u.rep) < ICB_MAXHOSTLEN) 192 strlcpy(is->host, q.u.rep, ICB_MAXHOSTLEN); 193 } 194 195 void 196 dns_rresolv(struct icb_session *is, struct sockaddr_storage *ss) 197 { 198 struct icbd_dnsquery q; 67 struct async *as; 199 68 200 69 if (!dodns) … … 204 73 syslog(LOG_DEBUG, "resolving: %s", is->host); 205 74 206 memset(&q, 0, sizeof q); 207 q.sid = is->id; 208 memcpy(&q.u.req, ss, sizeof *ss); 209 if (write(dns_pipe, &q, sizeof q) != sizeof q) { 210 syslog(LOG_ERR, "dns_rresolv write: %m"); 211 exit(EX_OSERR); 75 as = getnameinfo_async(sa, sa->sa_len, is->hostname, 76 sizeof is->hostname, NULL, 0, NI_NOFQDN, NULL); 77 async_run_event(as, dns_done, is); 78 } 79 80 /* Generic libevent glue for asr */ 81 82 struct async_event { 83 struct async *async; 84 struct event ev; 85 void (*callback)(int, struct async_res *, void *); 86 void *arg; 87 }; 88 89 void async_event_dispatch(int, short, void *); 90 91 struct async_event * 92 async_run_event(struct async * async, 93 void (*cb)(int, struct async_res *, void *), void *arg) 94 { 95 struct async_event *aev; 96 struct timeval tv; 97 98 aev = calloc(1, sizeof *aev); 99 if (aev == NULL) 100 return (NULL); 101 aev->async = async; 102 aev->callback = cb; 103 aev->arg = arg; 104 tv.tv_sec = 0; 105 tv.tv_usec = 0; 106 evtimer_set(&aev->ev, async_event_dispatch, aev); 107 evtimer_add(&aev->ev, &tv); 108 return (aev); 109 } 110 111 void 112 async_event_dispatch(int fd __attribute__((__unused__)), 113 short ev __attribute__((__unused__)), void *arg) 114 { 115 struct async_event *aev = arg; 116 struct async_res ar; 117 int r; 118 struct timeval tv; 119 120 while ((r = asr_async_run(aev->async, &ar)) == ASYNC_YIELD) 121 aev->callback(r, &ar, aev->arg); 122 123 event_del(&aev->ev); 124 if (r == ASYNC_COND) { 125 event_set(&aev->ev, ar.ar_fd, 126 ar.ar_cond == ASYNC_READ ? EV_READ : EV_WRITE, 127 async_event_dispatch, aev); 128 tv.tv_sec = ar.ar_timeout / 1000; 129 tv.tv_usec = (ar.ar_timeout % 1000) * 1000; 130 event_add(&aev->ev, &tv); 131 } else { /* ASYNC_DONE */ 132 aev->callback(r, &ar, aev->arg); 133 free(aev); 212 134 } 213 135 } -
icb.h
r718d0c9 re87ab6d 78 78 char client[ICB_MAXNICKLEN]; 79 79 char host[ICB_MAXHOSTLEN]; 80 char hostname[MAXHOSTNAMELEN]; 80 81 char buffer[ICB_MSGSIZE]; 81 82 struct event ev; -
icbd.c
r718d0c9 re87ab6d 39 39 #include <errno.h> 40 40 #include <err.h> 41 #include <resolv.h> 41 42 42 43 #include "icb.h" … … 231 232 logger_init(); 232 233 233 /* start a dns resolver thread*/234 dns_init();234 /* initialize resolver */ 235 res_init(); 235 236 236 237 if (!foreground) … … 636 637 is->host, sizeof is->host); 637 638 638 dns_rresolv(is, &ss);639 } 639 dns_rresolv(is, (struct sockaddr *)&ss); 640 } -
icbd.h
r718d0c9 re87ab6d 30 30 31 31 /* dns.c */ 32 struct sockaddr_storage; 33 int dns_init(void); 34 void dns_rresolv(struct icb_session *, struct sockaddr_storage *); 32 struct sockaddr; 33 void dns_rresolv(struct icb_session *, struct sockaddr *); 35 34 36 35 /* logger.c */
Note:
See TracChangeset
for help on using the changeset viewer.