1/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
| 1/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
|
2/* $FreeBSD: head/usr.sbin/ypldap/ypldap_dns.c 292270 2015-12-15 15:37:58Z araujo $ */
| 2/* $FreeBSD: head/usr.sbin/ypldap/ypldap_dns.c 297907 2016-04-13 03:36:34Z araujo $ */
|
3 4/* 5 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 16 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 17 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/types.h> 21#include <sys/param.h> 22#include <sys/socket.h> 23#include <sys/stat.h> 24#include <sys/time.h> 25#include <sys/tree.h> 26#include <sys/queue.h> 27 28#include <netinet/in.h> 29#include <arpa/nameser.h> 30 31#include <netdb.h> 32#include <pwd.h> 33#include <errno.h> 34#include <event.h> 35#include <resolv.h> 36#include <poll.h> 37#include <signal.h> 38#include <stdlib.h> 39#include <string.h> 40#include <unistd.h> 41#include <limits.h> 42 43#include "ypldap.h" 44 45volatile sig_atomic_t quit_dns = 0; 46struct imsgev *iev_dns; 47 48void dns_dispatch_imsg(int, short, void *); 49void dns_sig_handler(int, short, void *); 50void dns_shutdown(void);
| 3 4/* 5 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 16 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 17 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/types.h> 21#include <sys/param.h> 22#include <sys/socket.h> 23#include <sys/stat.h> 24#include <sys/time.h> 25#include <sys/tree.h> 26#include <sys/queue.h> 27 28#include <netinet/in.h> 29#include <arpa/nameser.h> 30 31#include <netdb.h> 32#include <pwd.h> 33#include <errno.h> 34#include <event.h> 35#include <resolv.h> 36#include <poll.h> 37#include <signal.h> 38#include <stdlib.h> 39#include <string.h> 40#include <unistd.h> 41#include <limits.h> 42 43#include "ypldap.h" 44 45volatile sig_atomic_t quit_dns = 0; 46struct imsgev *iev_dns; 47 48void dns_dispatch_imsg(int, short, void *); 49void dns_sig_handler(int, short, void *); 50void dns_shutdown(void);
|
51int host_dns(const char *s, struct ypldap_addr **hn);
| 51int host_dns(const char *, struct ypldap_addr_list *);
|
52 53void 54dns_sig_handler(int sig, short event, void *p) 55{ 56 switch (sig) { 57 case SIGINT: 58 case SIGTERM: 59 dns_shutdown(); 60 break; 61 default: 62 fatalx("unexpected signal"); 63 } 64} 65 66void 67dns_shutdown(void) 68{ 69 log_info("dns engine exiting"); 70 _exit(0); 71} 72 73pid_t 74ypldap_dns(int pipe_ntp[2], struct passwd *pw) 75{ 76 pid_t pid; 77 struct event ev_sigint; 78 struct event ev_sigterm; 79 struct event ev_sighup; 80 struct env env; 81 82 switch (pid = fork()) { 83 case -1: 84 fatal("cannot fork"); 85 break; 86 case 0: 87 break; 88 default: 89 return (pid); 90 } 91 92 setproctitle("dns engine"); 93 close(pipe_ntp[0]); 94 95 if (setgroups(1, &pw->pw_gid) || 96 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 97 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 98 fatal("can't drop privileges"); 99 endservent(); 100 101 event_init(); 102 signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL); 103 signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL); 104 signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL); 105 signal_add(&ev_sigint, NULL); 106 signal_add(&ev_sigterm, NULL); 107 signal_add(&ev_sighup, NULL); 108 109 if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL) 110 fatal(NULL); 111 112 env.sc_iev->events = EV_READ; 113 env.sc_iev->data = &env; 114 imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]); 115 env.sc_iev->handler = dns_dispatch_imsg; 116 event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events, 117 env.sc_iev->handler, &env); 118 event_add(&env.sc_iev->ev, NULL); 119 120 event_dispatch(); 121 dns_shutdown(); 122 123 return (0); 124} 125 126void 127dns_dispatch_imsg(int fd, short events, void *p) 128{ 129 struct imsg imsg; 130 int n, cnt; 131 char *name;
| 52 53void 54dns_sig_handler(int sig, short event, void *p) 55{ 56 switch (sig) { 57 case SIGINT: 58 case SIGTERM: 59 dns_shutdown(); 60 break; 61 default: 62 fatalx("unexpected signal"); 63 } 64} 65 66void 67dns_shutdown(void) 68{ 69 log_info("dns engine exiting"); 70 _exit(0); 71} 72 73pid_t 74ypldap_dns(int pipe_ntp[2], struct passwd *pw) 75{ 76 pid_t pid; 77 struct event ev_sigint; 78 struct event ev_sigterm; 79 struct event ev_sighup; 80 struct env env; 81 82 switch (pid = fork()) { 83 case -1: 84 fatal("cannot fork"); 85 break; 86 case 0: 87 break; 88 default: 89 return (pid); 90 } 91 92 setproctitle("dns engine"); 93 close(pipe_ntp[0]); 94 95 if (setgroups(1, &pw->pw_gid) || 96 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 97 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 98 fatal("can't drop privileges"); 99 endservent(); 100 101 event_init(); 102 signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL); 103 signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL); 104 signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL); 105 signal_add(&ev_sigint, NULL); 106 signal_add(&ev_sigterm, NULL); 107 signal_add(&ev_sighup, NULL); 108 109 if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL) 110 fatal(NULL); 111 112 env.sc_iev->events = EV_READ; 113 env.sc_iev->data = &env; 114 imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]); 115 env.sc_iev->handler = dns_dispatch_imsg; 116 event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events, 117 env.sc_iev->handler, &env); 118 event_add(&env.sc_iev->ev, NULL); 119 120 event_dispatch(); 121 dns_shutdown(); 122 123 return (0); 124} 125 126void 127dns_dispatch_imsg(int fd, short events, void *p) 128{ 129 struct imsg imsg; 130 int n, cnt; 131 char *name;
|
132 struct ypldap_addr *h, *hn;
| 132 struct ypldap_addr_list hn = TAILQ_HEAD_INITIALIZER(hn); 133 struct ypldap_addr *h;
|
133 struct ibuf *buf; 134 struct env *env = p; 135 struct imsgev *iev = env->sc_iev; 136 struct imsgbuf *ibuf = &iev->ibuf; 137 int shut = 0; 138 139 if ((events & (EV_READ | EV_WRITE)) == 0) 140 fatalx("unknown event"); 141 142 if (events & EV_READ) { 143 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 144 fatal("imsg_read error"); 145 if (n == 0) 146 shut = 1; 147 } 148 if (events & EV_WRITE) { 149 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 150 fatal("msgbuf_write"); 151 if (n == 0) 152 shut = 1; 153 goto done; 154 } 155 156 for (;;) { 157 if ((n = imsg_get(ibuf, &imsg)) == -1) 158 fatal("client_dispatch_imsg: imsg_get error"); 159 if (n == 0) 160 break; 161 162 switch (imsg.hdr.type) { 163 case IMSG_HOST_DNS: 164 name = imsg.data; 165 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) 166 fatalx("invalid IMSG_HOST_DNS received"); 167 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; 168 if (name[imsg.hdr.len] != '\0' || 169 strlen(name) != imsg.hdr.len) 170 fatalx("invalid IMSG_HOST_DNS received"); 171 if ((cnt = host_dns(name, &hn)) == -1) 172 break; 173 buf = imsg_create(ibuf, IMSG_HOST_DNS, 174 imsg.hdr.peerid, 0, 175 cnt * sizeof(struct sockaddr_storage)); 176 if (buf == NULL) 177 break; 178 if (cnt > 0) {
| 134 struct ibuf *buf; 135 struct env *env = p; 136 struct imsgev *iev = env->sc_iev; 137 struct imsgbuf *ibuf = &iev->ibuf; 138 int shut = 0; 139 140 if ((events & (EV_READ | EV_WRITE)) == 0) 141 fatalx("unknown event"); 142 143 if (events & EV_READ) { 144 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 145 fatal("imsg_read error"); 146 if (n == 0) 147 shut = 1; 148 } 149 if (events & EV_WRITE) { 150 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 151 fatal("msgbuf_write"); 152 if (n == 0) 153 shut = 1; 154 goto done; 155 } 156 157 for (;;) { 158 if ((n = imsg_get(ibuf, &imsg)) == -1) 159 fatal("client_dispatch_imsg: imsg_get error"); 160 if (n == 0) 161 break; 162 163 switch (imsg.hdr.type) { 164 case IMSG_HOST_DNS: 165 name = imsg.data; 166 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) 167 fatalx("invalid IMSG_HOST_DNS received"); 168 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; 169 if (name[imsg.hdr.len] != '\0' || 170 strlen(name) != imsg.hdr.len) 171 fatalx("invalid IMSG_HOST_DNS received"); 172 if ((cnt = host_dns(name, &hn)) == -1) 173 break; 174 buf = imsg_create(ibuf, IMSG_HOST_DNS, 175 imsg.hdr.peerid, 0, 176 cnt * sizeof(struct sockaddr_storage)); 177 if (buf == NULL) 178 break; 179 if (cnt > 0) {
|
179 h = hn; 180 while (h != NULL) {
| 180 while(!TAILQ_EMPTY(&hn)) { 181 h = TAILQ_FIRST(&hn); 182 TAILQ_REMOVE(&hn, h, next);
|
181 imsg_add(buf, &h->ss, sizeof(h->ss));
| 183 imsg_add(buf, &h->ss, sizeof(h->ss));
|
182 hn = h->next;
| |
183 free(h);
| 184 free(h);
|
184 h = hn;
| |
185 } 186 } 187 188 imsg_close(ibuf, buf); 189 break; 190 default: 191 break; 192 } 193 imsg_free(&imsg); 194 } 195 196done: 197 if (!shut) 198 imsg_event_add(iev); 199 else { 200 /* this pipe is dead, so remove the event handler */ 201 event_del(&iev->ev); 202 event_loopexit(NULL); 203 } 204} 205 206int
| 185 } 186 } 187 188 imsg_close(ibuf, buf); 189 break; 190 default: 191 break; 192 } 193 imsg_free(&imsg); 194 } 195 196done: 197 if (!shut) 198 imsg_event_add(iev); 199 else { 200 /* this pipe is dead, so remove the event handler */ 201 event_del(&iev->ev); 202 event_loopexit(NULL); 203 } 204} 205 206int
|
207host_dns(const char *s, struct ypldap_addr **hn)
| 207host_dns(const char *s, struct ypldap_addr_list *hn)
|
208{ 209 struct addrinfo hints, *res0, *res; 210 int error, cnt = 0; 211 struct sockaddr_in *sa_in; 212 struct sockaddr_in6 *sa_in6;
| 208{ 209 struct addrinfo hints, *res0, *res; 210 int error, cnt = 0; 211 struct sockaddr_in *sa_in; 212 struct sockaddr_in6 *sa_in6;
|
213 struct ypldap_addr *h, *hh = NULL;
| 213 struct ypldap_addr *h;
|
214 215 bzero(&hints, sizeof(hints)); 216 hints.ai_family = PF_UNSPEC; 217 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 218 error = getaddrinfo(s, NULL, &hints, &res0); 219 if (error == EAI_AGAIN || error == EAI_NONAME) 220 return (0); 221 if (error) { 222 log_warnx("could not parse \"%s\": %s", s, 223 gai_strerror(error)); 224 return (-1); 225 } 226 227 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) { 228 if (res->ai_family != AF_INET && 229 res->ai_family != AF_INET6) 230 continue; 231 if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL) 232 fatal(NULL); 233 h->ss.ss_family = res->ai_family; 234 if (res->ai_family == AF_INET) { 235 sa_in = (struct sockaddr_in *)&h->ss; 236 sa_in->sin_len = sizeof(struct sockaddr_in); 237 sa_in->sin_addr.s_addr = ((struct sockaddr_in *) 238 res->ai_addr)->sin_addr.s_addr; 239 } else { 240 sa_in6 = (struct sockaddr_in6 *)&h->ss; 241 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 242 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *) 243 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 244 } 245
| 214 215 bzero(&hints, sizeof(hints)); 216 hints.ai_family = PF_UNSPEC; 217 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 218 error = getaddrinfo(s, NULL, &hints, &res0); 219 if (error == EAI_AGAIN || error == EAI_NONAME) 220 return (0); 221 if (error) { 222 log_warnx("could not parse \"%s\": %s", s, 223 gai_strerror(error)); 224 return (-1); 225 } 226 227 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) { 228 if (res->ai_family != AF_INET && 229 res->ai_family != AF_INET6) 230 continue; 231 if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL) 232 fatal(NULL); 233 h->ss.ss_family = res->ai_family; 234 if (res->ai_family == AF_INET) { 235 sa_in = (struct sockaddr_in *)&h->ss; 236 sa_in->sin_len = sizeof(struct sockaddr_in); 237 sa_in->sin_addr.s_addr = ((struct sockaddr_in *) 238 res->ai_addr)->sin_addr.s_addr; 239 } else { 240 sa_in6 = (struct sockaddr_in6 *)&h->ss; 241 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 242 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *) 243 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 244 } 245
|
246 h->next = hh; 247 hh = h;
| 246 TAILQ_INSERT_HEAD(hn, h, next);
|
248 cnt++; 249 } 250 freeaddrinfo(res0);
| 247 cnt++; 248 } 249 freeaddrinfo(res0);
|
251 252 *hn = hh;
| |
253 return (cnt); 254}
| 250 return (cnt); 251}
|