1 /* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
4 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <sys/socket.h>
25 #include <sys/queue.h>
27 #include <netinet/in.h>
28 #include <arpa/nameser.h>
44 volatile sig_atomic_t quit_dns = 0;
45 struct imsgev *iev_dns;
47 void dns_dispatch_imsg(int, short, void *);
48 void dns_sig_handler(int, short, void *);
49 void dns_shutdown(void);
50 int host_dns(const char *, struct ypldap_addr_list *);
53 dns_sig_handler(int sig, short event, void *p)
61 fatalx("unexpected signal");
68 log_info("dns engine exiting");
73 ypldap_dns(int pipe_ntp[2], struct passwd *pw)
76 struct event ev_sigint;
77 struct event ev_sigterm;
78 struct event ev_sighup;
81 switch (pid = fork()) {
91 setproctitle("dns engine");
94 if (setgroups(1, &pw->pw_gid) ||
95 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
96 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
97 fatal("can't drop privileges");
101 signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL);
102 signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL);
103 signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL);
104 signal_add(&ev_sigint, NULL);
105 signal_add(&ev_sigterm, NULL);
106 signal_add(&ev_sighup, NULL);
108 if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
111 env.sc_iev->events = EV_READ;
112 env.sc_iev->data = &env;
113 imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]);
114 env.sc_iev->handler = dns_dispatch_imsg;
115 event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
116 env.sc_iev->handler, &env);
117 event_add(&env.sc_iev->ev, NULL);
126 dns_dispatch_imsg(int fd, short events, void *p)
131 struct ypldap_addr_list hn = TAILQ_HEAD_INITIALIZER(hn);
132 struct ypldap_addr *h;
135 struct imsgev *iev = env->sc_iev;
136 struct imsgbuf *ibuf = &iev->ibuf;
139 if ((events & (EV_READ | EV_WRITE)) == 0)
140 fatalx("unknown event");
142 if (events & EV_READ) {
143 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
144 fatal("imsg_read error");
148 if (events & EV_WRITE) {
149 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
150 fatal("msgbuf_write");
157 if ((n = imsg_get(ibuf, &imsg)) == -1)
158 fatal("client_dispatch_imsg: imsg_get error");
162 switch (imsg.hdr.type) {
165 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
166 fatalx("invalid IMSG_HOST_DNS received");
167 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
168 if (name[imsg.hdr.len] != '\0' ||
169 strlen(name) != imsg.hdr.len)
170 fatalx("invalid IMSG_HOST_DNS received");
171 if ((cnt = host_dns(name, &hn)) == -1)
173 buf = imsg_create(ibuf, IMSG_HOST_DNS,
175 cnt * sizeof(struct sockaddr_storage));
179 while(!TAILQ_EMPTY(&hn)) {
180 h = TAILQ_FIRST(&hn);
181 TAILQ_REMOVE(&hn, h, next);
182 imsg_add(buf, &h->ss, sizeof(h->ss));
187 imsg_close(ibuf, buf);
199 /* this pipe is dead, so remove the event handler */
201 event_loopexit(NULL);
206 host_dns(const char *s, struct ypldap_addr_list *hn)
208 struct addrinfo hints, *res0, *res;
210 struct sockaddr_in *sa_in;
211 struct sockaddr_in6 *sa_in6;
212 struct ypldap_addr *h;
214 memset(&hints, 0, sizeof(hints));
215 hints.ai_family = PF_UNSPEC;
216 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
217 error = getaddrinfo(s, NULL, &hints, &res0);
218 if (error == EAI_AGAIN || error == EAI_NONAME)
221 log_warnx("could not parse \"%s\": %s", s,
222 gai_strerror(error));
226 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
227 if (res->ai_family != AF_INET &&
228 res->ai_family != AF_INET6)
230 if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL)
232 h->ss.ss_family = res->ai_family;
233 if (res->ai_family == AF_INET) {
234 sa_in = (struct sockaddr_in *)&h->ss;
235 sa_in->sin_len = sizeof(struct sockaddr_in);
236 sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
237 res->ai_addr)->sin_addr.s_addr;
239 sa_in6 = (struct sockaddr_in6 *)&h->ss;
240 sa_in6->sin6_len = sizeof(struct sockaddr_in6);
241 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
242 res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
245 TAILQ_INSERT_HEAD(hn, h, next);