1 /* $OpenBSD: ntp_dns.c,v 1.5 2014/02/10 09:12:34 dtucker Exp $ */ 2 3 /* 4 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org> 5 * 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. 9 * 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. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/resource.h> 21 #include <sys/time.h> 22 23 #include <err.h> 24 #include <errno.h> 25 #include <poll.h> 26 #include <signal.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "ntpd.h" 32 33 volatile sig_atomic_t quit_dns = 0; 34 struct imsgbuf *ibuf_dns; 35 36 void sighdlr_dns(int); 37 int dns_dispatch_imsg(void); 38 39 void 40 sighdlr_dns(int sig) 41 { 42 switch (sig) { 43 case SIGTERM: 44 case SIGINT: 45 quit_dns = 1; 46 break; 47 } 48 } 49 50 pid_t 51 ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) 52 { 53 pid_t pid; 54 struct pollfd pfd[1]; 55 int nfds; 56 57 switch (pid = fork()) { 58 case -1: 59 fatal("cannot fork"); 60 break; 61 case 0: 62 break; 63 default: 64 return (pid); 65 } 66 67 if (setpriority(PRIO_PROCESS, 0, 0) == -1) 68 warn("could not set priority"); 69 70 /* in this case the parent didn't init logging and didn't daemonize */ 71 if (nconf->settime && !nconf->debug) { 72 log_init(nconf->debug); 73 if (setsid() == -1) 74 fatal("setsid"); 75 } 76 77 setproctitle("dns engine"); 78 close(pipe_ntp[0]); 79 80 if (setgroups(1, &pw->pw_gid) || 81 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 82 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 83 fatal("can't drop privileges"); 84 85 signal(SIGTERM, sighdlr_dns); 86 signal(SIGINT, sighdlr_dns); 87 signal(SIGHUP, sighdlr_dns); 88 89 if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) 90 fatal(NULL); 91 imsg_init(ibuf_dns, pipe_ntp[1]); 92 93 while (quit_dns == 0) { 94 pfd[0].fd = ibuf_dns->fd; 95 pfd[0].events = POLLIN; 96 if (ibuf_dns->w.queued) 97 pfd[0].events |= POLLOUT; 98 99 if ((nfds = poll(pfd, 1, INFTIM)) == -1) 100 if (errno != EINTR) { 101 log_warn("poll error"); 102 quit_dns = 1; 103 } 104 105 if (nfds > 0 && (pfd[0].revents & POLLOUT)) 106 if (msgbuf_write(&ibuf_dns->w) <= 0 && 107 errno != EAGAIN) { 108 log_warn("pipe write error (to ntp engine)"); 109 quit_dns = 1; 110 } 111 112 if (nfds > 0 && pfd[0].revents & POLLIN) { 113 nfds--; 114 if (dns_dispatch_imsg() == -1) 115 quit_dns = 1; 116 } 117 } 118 119 msgbuf_clear(&ibuf_dns->w); 120 free(ibuf_dns); 121 _exit(0); 122 } 123 124 int 125 dns_dispatch_imsg(void) 126 { 127 struct imsg imsg; 128 int n, cnt; 129 char *name; 130 struct ntp_addr *h, *hn; 131 struct ibuf *buf; 132 133 if ((n = imsg_read(ibuf_dns)) == -1) 134 return (-1); 135 136 if (n == 0) { /* connection closed */ 137 log_warnx("dispatch_imsg in main: pipe closed"); 138 return (-1); 139 } 140 141 for (;;) { 142 if ((n = imsg_get(ibuf_dns, &imsg)) == -1) 143 return (-1); 144 145 if (n == 0) 146 break; 147 148 switch (imsg.hdr.type) { 149 case IMSG_HOST_DNS: 150 name = imsg.data; 151 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) 152 fatalx("invalid IMSG_HOST_DNS received"); 153 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; 154 if (name[imsg.hdr.len] != '\0' || 155 strlen(name) != imsg.hdr.len) 156 fatalx("invalid IMSG_HOST_DNS received"); 157 if ((cnt = host_dns(name, &hn)) == -1) 158 break; 159 buf = imsg_create(ibuf_dns, IMSG_HOST_DNS, 160 imsg.hdr.peerid, 0, 161 cnt * sizeof(struct sockaddr_storage)); 162 if (buf == NULL) 163 break; 164 if (cnt > 0) 165 for (h = hn; h != NULL; h = h->next) 166 imsg_add(buf, &h->ss, sizeof(h->ss)); 167 168 imsg_close(ibuf_dns, buf); 169 break; 170 default: 171 break; 172 } 173 imsg_free(&imsg); 174 } 175 return (0); 176 } 177