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