int dispatch_imsg(struct ntpd_conf *lconf) { struct imsg imsg; int n, cnt; double d; char *name; struct ntp_addr *h, *hn; struct ibuf *buf; if ((n = imsg_read(ibuf)) == -1) return (-1); if (n == 0) { /* connection closed */ log_warnx("dispatch_imsg in main: pipe closed"); return (-1); } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) return (-1); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_ADJTIME: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) fatalx("invalid IMSG_ADJTIME received"); memcpy(&d, imsg.data, sizeof(d)); n = ntpd_adjtime(d); imsg_compose(ibuf, IMSG_ADJTIME, 0, 0, -1, &n, sizeof(n)); break; case IMSG_ADJFREQ: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) fatalx("invalid IMSG_ADJFREQ received"); memcpy(&d, imsg.data, sizeof(d)); ntpd_adjfreq(d, 1); break; case IMSG_SETTIME: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) fatalx("invalid IMSG_SETTIME received"); if (!lconf->settime) break; log_init(lconf->debug); memcpy(&d, imsg.data, sizeof(d)); ntpd_settime(d); /* daemonize now */ if (!lconf->debug) if (daemon(1, 0)) fatal("daemon"); lconf->settime = 0; timeout = INFTIM; break; case IMSG_HOST_DNS: name = imsg.data; if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) fatalx("invalid IMSG_HOST_DNS received"); imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; if (name[imsg.hdr.len] != '\0' || strlen(name) != imsg.hdr.len) fatalx("invalid IMSG_HOST_DNS received"); if ((cnt = host_dns(name, &hn)) == -1) break; buf = imsg_create(ibuf, IMSG_HOST_DNS, imsg.hdr.peerid, 0, cnt * sizeof(struct sockaddr_storage)); if (buf == NULL) break; if (cnt > 0) for (h = hn; h != NULL; h = h->next) imsg_add(buf, &h->ss, sizeof(h->ss)); imsg_close(ibuf, buf); break; default: break; } imsg_free(&imsg); } return (0); }
void dns_dispatch_imsg(int fd, short events, void *p) { struct imsg imsg; int n, cnt; char *name; struct ypldap_addr_list hn = TAILQ_HEAD_INITIALIZER(hn); struct ypldap_addr *h; struct ibuf *buf; struct env *env = p; struct imsgev *iev = env->sc_iev; struct imsgbuf *ibuf = &iev->ibuf; int shut = 0; if ((events & (EV_READ | EV_WRITE)) == 0) fatalx("unknown event"); if (events & EV_READ) { if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) fatal("imsg_read error"); if (n == 0) shut = 1; } if (events & EV_WRITE) { if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) fatal("msgbuf_write"); if (n == 0) shut = 1; goto done; } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("client_dispatch_imsg: imsg_get error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_HOST_DNS: name = imsg.data; if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) fatalx("invalid IMSG_HOST_DNS received"); imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; if (name[imsg.hdr.len] != '\0' || strlen(name) != imsg.hdr.len) fatalx("invalid IMSG_HOST_DNS received"); if ((cnt = host_dns(name, &hn)) == -1) break; buf = imsg_create(ibuf, IMSG_HOST_DNS, imsg.hdr.peerid, 0, cnt * sizeof(struct sockaddr_storage)); if (buf == NULL) break; if (cnt > 0) { while(!TAILQ_EMPTY(&hn)) { h = TAILQ_FIRST(&hn); TAILQ_REMOVE(&hn, h, next); imsg_add(buf, &h->ss, sizeof(h->ss)); free(h); } } imsg_close(ibuf, buf); break; default: break; } imsg_free(&imsg); } done: if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }
int dnsproc(int nfd) { int rc, cc; char *look, *last; struct addr v[MAX_SERVERS_DNS]; long lval; size_t i; ssize_t vsz; enum dnsop op; rc = 0; look = last = NULL; vsz = 0; /* * Why don't we chroot() here? * On OpenBSD, the pledge(2) takes care of our constraining the * environment to DNS resolution only, so the chroot(2) is * unnecessary. * On Mac OS X, we can't chroot(2): we'd need to have an mdns * responder thing in each jail. * On Linux, forget it. getaddrinfo(2) pulls on all sorts of * mystery meat. */ if ( ! sandbox_before()) goto out; else if ( ! dropprivs()) goto out; else if ( ! sandbox_after()) goto out; /* * This is simple: just loop on a request operation, and each * time we write back zero or more entries. * Also do a simple trick and cache the last lookup. */ for (;;) { op = DNS__MAX; if (0 == (lval = readop(nfd, COMM_DNS))) op = DNS_STOP; else if (DNS_LOOKUP == lval) op = lval; if (DNS__MAX == op) { warnx("unknown operation from netproc"); goto out; } else if (DNS_STOP == op) break; if (NULL == (look = readstr(nfd, COMM_DNSQ))) goto out; /* * Check if we're asked to repeat the lookup. * If not, request it from host_dns(). */ if (NULL == last || strcmp(look, last)) { if ((vsz = host_dns(look, v)) < 0) goto out; free(last); last = look; look = NULL; } else { doddbg("%s: cached", look); free(look); look = NULL; } if (0 == (cc = writeop(nfd, COMM_DNSLEN, vsz))) break; else if (cc < 0) goto out; for (i = 0; i < (size_t)vsz; i++) { if (writeop(nfd, COMM_DNSF, v[i].family) <= 0) goto out; if (writestr(nfd, COMM_DNSA, v[i].ip) <= 0) goto out; } } rc = 1; out: close(nfd); free(look); free(last); return(rc); }