ypldap_dns.c revision 292270
150276Speter/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */ 2176187Srafan/* $FreeBSD: head/usr.sbin/ypldap/ypldap_dns.c 292270 2015-12-15 15:37:58Z araujo $ */ 350276Speter 450276Speter/* 550276Speter * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org> 650276Speter * 750276Speter * Permission to use, copy, modify, and distribute this software for any 850276Speter * purpose with or without fee is hereby granted, provided that the above 950276Speter * copyright notice and this permission notice appear in all copies. 1050276Speter * 1150276Speter * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1250276Speter * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1350276Speter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1450276Speter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1550276Speter * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 1650276Speter * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 1750276Speter * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1850276Speter */ 1950276Speter 2050276Speter#include <sys/types.h> 2150276Speter#include <sys/param.h> 2250276Speter#include <sys/socket.h> 2350276Speter#include <sys/stat.h> 2450276Speter#include <sys/time.h> 2550276Speter#include <sys/tree.h> 2650276Speter#include <sys/queue.h> 2750276Speter 2850276Speter#include <netinet/in.h> 2950276Speter#include <arpa/nameser.h> 30166124Srafan 3150276Speter#include <netdb.h> 32166124Srafan#include <pwd.h> 3350276Speter#include <errno.h> 3450276Speter#include <event.h> 35184989Srafan#include <resolv.h> 3650276Speter#include <poll.h> 3750276Speter#include <signal.h> 3850276Speter#include <stdlib.h> 39166124Srafan#include <string.h> 4050276Speter#include <unistd.h> 4150276Speter#include <limits.h> 4250276Speter 4350276Speter#include "ypldap.h" 4450276Speter 45166124Srafanvolatile sig_atomic_t quit_dns = 0; 4650276Speterstruct imsgev *iev_dns; 4750276Speter 4850276Spetervoid dns_dispatch_imsg(int, short, void *); 4950276Spetervoid dns_sig_handler(int, short, void *); 5050276Spetervoid dns_shutdown(void); 5150276Speterint host_dns(const char *s, struct ypldap_addr **hn); 5250276Speter 5350276Spetervoid 5450276Speterdns_sig_handler(int sig, short event, void *p) 5550276Speter{ 56166124Srafan switch (sig) { 5750276Speter case SIGINT: 58166124Srafan case SIGTERM: 5950276Speter dns_shutdown(); 6050276Speter break; 61166124Srafan default: 6250276Speter fatalx("unexpected signal"); 6350276Speter } 6450276Speter} 6550276Speter 6650276Spetervoid 6750276Speterdns_shutdown(void) 6850276Speter{ 6950276Speter log_info("dns engine exiting"); 7050276Speter _exit(0); 7150276Speter} 7250276Speter 7350276Speterpid_t 7450276Speterypldap_dns(int pipe_ntp[2], struct passwd *pw) 7550276Speter{ 7650276Speter pid_t pid; 7750276Speter struct event ev_sigint; 7850276Speter struct event ev_sigterm; 7950276Speter struct event ev_sighup; 8050276Speter struct env env; 8150276Speter 82166124Srafan switch (pid = fork()) { 8350276Speter case -1: 8450276Speter fatal("cannot fork"); 8550276Speter break; 86166124Srafan case 0: 8750276Speter break; 8850276Speter default: 8950276Speter return (pid); 90166124Srafan } 9150276Speter 9250276Speter setproctitle("dns engine"); 9350276Speter close(pipe_ntp[0]); 94166124Srafan 9550276Speter if (setgroups(1, &pw->pw_gid) || 96166124Srafan setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 9750276Speter setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 9850276Speter fatal("can't drop privileges"); 9950276Speter endservent(); 10050276Speter 101166124Srafan event_init(); 102166124Srafan signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL); 103166124Srafan signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL); 104166124Srafan signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL); 105166124Srafan signal_add(&ev_sigint, NULL); 106166124Srafan signal_add(&ev_sigterm, NULL); 107166124Srafan signal_add(&ev_sighup, NULL); 108166124Srafan 109166124Srafan if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL) 110166124Srafan fatal(NULL); 111166124Srafan 112166124Srafan env.sc_iev->events = EV_READ; 11350276Speter env.sc_iev->data = &env; 11450276Speter imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]); 11550276Speter env.sc_iev->handler = dns_dispatch_imsg; 116166124Srafan event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events, 117166124Srafan env.sc_iev->handler, &env); 118166124Srafan event_add(&env.sc_iev->ev, NULL); 11950276Speter 12050276Speter event_dispatch(); 121166124Srafan dns_shutdown(); 12250276Speter 12350276Speter return (0); 12450276Speter} 12550276Speter 12650276Spetervoid 12750276Speterdns_dispatch_imsg(int fd, short events, void *p) 12850276Speter{ 12950276Speter struct imsg imsg; 13050276Speter int n, cnt; 13150276Speter char *name; 13250276Speter struct ypldap_addr *h, *hn; 13350276Speter struct ibuf *buf; 13450276Speter struct env *env = p; 13550276Speter struct imsgev *iev = env->sc_iev; 13650276Speter struct imsgbuf *ibuf = &iev->ibuf; 13750276Speter int shut = 0; 13850276Speter 13950276Speter if ((events & (EV_READ | EV_WRITE)) == 0) 14050276Speter fatalx("unknown event"); 14150276Speter 14250276Speter if (events & EV_READ) { 14350276Speter if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 14450276Speter fatal("imsg_read error"); 14550276Speter if (n == 0) 14650276Speter shut = 1; 14750276Speter } 14850276Speter if (events & EV_WRITE) { 14950276Speter if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 15050276Speter fatal("msgbuf_write"); 15150276Speter if (n == 0) 15250276Speter shut = 1; 15350276Speter goto done; 15450276Speter } 15550276Speter 15650276Speter for (;;) { 15750276Speter if ((n = imsg_get(ibuf, &imsg)) == -1) 15850276Speter fatal("client_dispatch_imsg: imsg_get error"); 15950276Speter if (n == 0) 16050276Speter break; 16150276Speter 16250276Speter switch (imsg.hdr.type) { 16350276Speter case IMSG_HOST_DNS: 16450276Speter name = imsg.data; 165166124Srafan if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) 16650276Speter fatalx("invalid IMSG_HOST_DNS received"); 16750276Speter imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; 16850276Speter if (name[imsg.hdr.len] != '\0' || 16950276Speter strlen(name) != imsg.hdr.len) 17050276Speter fatalx("invalid IMSG_HOST_DNS received"); 17150276Speter if ((cnt = host_dns(name, &hn)) == -1) 17250276Speter break; 17350276Speter buf = imsg_create(ibuf, IMSG_HOST_DNS, 17450276Speter imsg.hdr.peerid, 0, 17550276Speter cnt * sizeof(struct sockaddr_storage)); 17650276Speter if (buf == NULL) 17750276Speter break; 17850276Speter if (cnt > 0) { 17950276Speter h = hn; 18050276Speter while (h != NULL) { 18150276Speter imsg_add(buf, &h->ss, sizeof(h->ss)); 18250276Speter hn = h->next; 18350276Speter free(h); 18450276Speter h = hn; 18550276Speter } 18650276Speter } 18750276Speter 18850276Speter imsg_close(ibuf, buf); 18950276Speter break; 19050276Speter default: 19150276Speter break; 19250276Speter } 19350276Speter imsg_free(&imsg); 19450276Speter } 19550276Speter 19650276Speterdone: 19750276Speter if (!shut) 19850276Speter imsg_event_add(iev); 19950276Speter else { 20050276Speter /* this pipe is dead, so remove the event handler */ 20150276Speter event_del(&iev->ev); 20250276Speter event_loopexit(NULL); 20350276Speter } 20450276Speter} 20550276Speter 20650276Speterint 207166124Srafanhost_dns(const char *s, struct ypldap_addr **hn) 208166124Srafan{ 209166124Srafan struct addrinfo hints, *res0, *res; 210166124Srafan int error, cnt = 0; 211166124Srafan struct sockaddr_in *sa_in; 212166124Srafan struct sockaddr_in6 *sa_in6; 213166124Srafan struct ypldap_addr *h, *hh = NULL; 214166124Srafan 215166124Srafan bzero(&hints, sizeof(hints)); 216166124Srafan hints.ai_family = PF_UNSPEC; 217166124Srafan hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 218166124Srafan error = getaddrinfo(s, NULL, &hints, &res0); 219166124Srafan if (error == EAI_AGAIN || error == EAI_NONAME) 220166124Srafan return (0); 221166124Srafan if (error) { 222166124Srafan log_warnx("could not parse \"%s\": %s", s, 223166124Srafan gai_strerror(error)); 224166124Srafan return (-1); 225166124Srafan } 226166124Srafan 227166124Srafan for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) { 228166124Srafan if (res->ai_family != AF_INET && 229166124Srafan res->ai_family != AF_INET6) 230166124Srafan continue; 231166124Srafan if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL) 232166124Srafan fatal(NULL); 233166124Srafan h->ss.ss_family = res->ai_family; 234166124Srafan if (res->ai_family == AF_INET) { 235166124Srafan sa_in = (struct sockaddr_in *)&h->ss; 236166124Srafan sa_in->sin_len = sizeof(struct sockaddr_in); 237166124Srafan sa_in->sin_addr.s_addr = ((struct sockaddr_in *) 238166124Srafan res->ai_addr)->sin_addr.s_addr; 239166124Srafan } else { 240166124Srafan sa_in6 = (struct sockaddr_in6 *)&h->ss; 241166124Srafan sa_in6->sin6_len = sizeof(struct sockaddr_in6); 242166124Srafan memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *) 243166124Srafan res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 244166124Srafan } 245166124Srafan 246166124Srafan h->next = hh; 247166124Srafan hh = h; 248166124Srafan cnt++; 249166124Srafan } 250166124Srafan freeaddrinfo(res0); 251166124Srafan 252166124Srafan *hn = hh; 253166124Srafan return (cnt); 254166124Srafan} 255166124Srafan