1 /* $OpenBSD: ntp_dns.c,v 1.18 2016/09/14 13:20:16 rzalamena 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 USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.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 <fcntl.h> 27 #include <signal.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <syslog.h> 31 #include <unistd.h> 32 33 #include "ntpd.h" 34 35 volatile sig_atomic_t quit_dns = 0; 36 struct imsgbuf *ibuf_dns; 37 38 void sighdlr_dns(int); 39 int dns_dispatch_imsg(void); 40 41 void 42 sighdlr_dns(int sig) 43 { 44 switch (sig) { 45 case SIGTERM: 46 case SIGINT: 47 quit_dns = 1; 48 break; 49 } 50 } 51 52 void 53 ntp_dns(struct ntpd_conf *nconf, struct passwd *pw) 54 { 55 struct pollfd pfd[1]; 56 int nfds, nullfd; 57 58 if (setpriority(PRIO_PROCESS, 0, 0) == -1) 59 log_warn("could not set priority"); 60 61 /* in this case the parent didn't init logging and didn't daemonize */ 62 if (nconf->settime && !nconf->debug) { 63 log_init(nconf->debug, LOG_DAEMON); 64 if (setsid() == -1) 65 fatal("setsid"); 66 } 67 log_procinit("dns"); 68 69 if ((nullfd = open("/dev/null", O_RDWR, 0)) == -1) 70 fatal(NULL); 71 72 if (!nconf->debug) { 73 dup2(nullfd, STDIN_FILENO); 74 dup2(nullfd, STDOUT_FILENO); 75 dup2(nullfd, STDERR_FILENO); 76 } 77 close(nullfd); 78 79 setproctitle("dns engine"); 80 81 if (setgroups(1, &pw->pw_gid) || 82 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 83 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 84 fatal("can't drop privileges"); 85 86 signal(SIGTERM, sighdlr_dns); 87 signal(SIGINT, sighdlr_dns); 88 signal(SIGHUP, SIG_IGN); 89 90 if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) 91 fatal(NULL); 92 imsg_init(ibuf_dns, PARENT_SOCK_FILENO); 93 94 if (pledge("stdio dns", NULL) == -1) 95 err(1, "pledge"); 96 97 while (quit_dns == 0) { 98 pfd[0].fd = ibuf_dns->fd; 99 pfd[0].events = POLLIN; 100 if (ibuf_dns->w.queued) 101 pfd[0].events |= POLLOUT; 102 103 if ((nfds = poll(pfd, 1, INFTIM)) == -1) 104 if (errno != EINTR) { 105 log_warn("poll error"); 106 quit_dns = 1; 107 } 108 109 if (nfds > 0 && (pfd[0].revents & POLLOUT)) 110 if (msgbuf_write(&ibuf_dns->w) <= 0 && 111 errno != EAGAIN) { 112 log_warn("pipe write error (to ntp engine)"); 113 quit_dns = 1; 114 } 115 116 if (nfds > 0 && pfd[0].revents & POLLIN) { 117 nfds--; 118 if (dns_dispatch_imsg() == -1) 119 quit_dns = 1; 120 } 121 } 122 123 msgbuf_clear(&ibuf_dns->w); 124 free(ibuf_dns); 125 exit(0); 126 } 127 128 int 129 dns_dispatch_imsg(void) 130 { 131 struct imsg imsg; 132 int n, cnt; 133 char *name; 134 struct ntp_addr *h, *hn; 135 struct ibuf *buf; 136 const char *str; 137 138 if ((n = imsg_read(ibuf_dns)) == -1 && errno != EAGAIN) 139 return (-1); 140 141 if (n == 0) { /* connection closed */ 142 log_warnx("dispatch_imsg in main: pipe closed"); 143 return (-1); 144 } 145 146 for (;;) { 147 if ((n = imsg_get(ibuf_dns, &imsg)) == -1) 148 return (-1); 149 150 if (n == 0) 151 break; 152 153 switch (imsg.hdr.type) { 154 case IMSG_HOST_DNS: 155 case IMSG_CONSTRAINT_DNS: 156 if (imsg.hdr.type == IMSG_HOST_DNS) 157 str = "IMSG_HOST_DNS"; 158 else 159 str = "IMSG_CONSTRAINT_DNS"; 160 name = imsg.data; 161 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) 162 fatalx("invalid %s received", str); 163 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; 164 if (name[imsg.hdr.len] != '\0' || 165 strlen(name) != imsg.hdr.len) 166 fatalx("invalid %s received", str); 167 if ((cnt = host_dns(name, &hn)) == -1) 168 break; 169 buf = imsg_create(ibuf_dns, imsg.hdr.type, 170 imsg.hdr.peerid, 0, 171 cnt * sizeof(struct sockaddr_storage)); 172 if (cnt > 0) { 173 if (buf) { 174 for (h = hn; h != NULL; h = h->next) 175 if (imsg_add(buf, &h->ss, 176 sizeof(h->ss)) == -1) { 177 buf = NULL; 178 break; 179 } 180 } 181 host_dns_free(hn); 182 hn = NULL; 183 } 184 if (buf) 185 imsg_close(ibuf_dns, buf); 186 break; 187 default: 188 break; 189 } 190 imsg_free(&imsg); 191 } 192 return (0); 193 } 194