xref: /openbsd-src/sbin/unwind/frontend.c (revision 5e3c7963eb248119b7dfd4b0defad58a7d9cd306)
1 /*	$OpenBSD: frontend.c,v 1.5 2019/01/27 12:40:54 florian Exp $	*/
2 
3 /*
4  * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/queue.h>
24 #include <sys/socket.h>
25 #include <sys/syslog.h>
26 #include <sys/uio.h>
27 
28 #include <netinet/in.h>
29 #include <net/if.h>
30 #include <net/route.h>
31 
32 #include <errno.h>
33 #include <event.h>
34 #include <imsg.h>
35 #include <netdb.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44 
45 #include "libunbound/config.h"
46 #include "libunbound/sldns/pkthdr.h"
47 #include "libunbound/sldns/sbuffer.h"
48 #include "libunbound/sldns/wire2str.h"
49 
50 #include "uw_log.h"
51 #include "unwind.h"
52 #include "frontend.h"
53 #include "control.h"
54 
55 #define	ROUTE_SOCKET_BUF_SIZE   16384
56 
57 struct udp_ev {
58 	struct event		 ev;
59 	uint8_t			 query[65536];
60 	struct msghdr		 rcvmhdr;
61 	struct iovec		 rcviov[1];
62 	struct sockaddr_storage	 from;
63 } udp4ev, udp6ev;
64 
65 struct pending_query {
66 	TAILQ_ENTRY(pending_query)	 entry;
67 	struct sockaddr_storage		 from;
68 	uint8_t				*query;
69 	ssize_t				 len;
70 	uint64_t			 imsg_id;
71 	int				 fd;
72 	int				 bogus;
73 };
74 
75 TAILQ_HEAD(, pending_query)	 pending_queries;
76 
77 __dead void		 frontend_shutdown(void);
78 void			 frontend_sig_handler(int, short, void *);
79 void			 frontend_startup(void);
80 void			 udp_receive(int, short, void *);
81 void			 send_answer(struct pending_query *, uint8_t *,
82 			     ssize_t);
83 void			 route_receive(int, short, void *);
84 void			 handle_route_message(struct rt_msghdr *,
85 			     struct sockaddr **);
86 void			 get_rtaddrs(int, struct sockaddr *,
87 			     struct sockaddr **);
88 void			 rtmget_default(void);
89 char			*ip_port(struct sockaddr *);
90 struct pending_query	*find_pending_query(uint64_t);
91 void			 parse_dhcp_lease(int);
92 
93 struct unwind_conf	*frontend_conf;
94 struct imsgev		*iev_main;
95 struct imsgev		*iev_resolver;
96 struct event		 ev_route;
97 int			 udp4sock = -1, udp6sock = -1, routesock = -1;
98 
99 void
100 frontend_sig_handler(int sig, short event, void *bula)
101 {
102 	/*
103 	 * Normal signal handler rules don't apply because libevent
104 	 * decouples for us.
105 	 */
106 
107 	switch (sig) {
108 	case SIGINT:
109 	case SIGTERM:
110 		frontend_shutdown();
111 	default:
112 		fatalx("unexpected signal");
113 	}
114 }
115 
116 void
117 frontend(int debug, int verbose)
118 {
119 	struct event		 ev_sigint, ev_sigterm;
120 	struct passwd		*pw;
121 	size_t			 rcvcmsglen, sndcmsgbuflen;
122 	uint8_t			*rcvcmsgbuf;
123 	uint8_t			*sndcmsgbuf = NULL;
124 
125 	frontend_conf = config_new_empty();
126 	control_state.fd = -1;
127 
128 	log_init(debug, LOG_DAEMON);
129 	log_setverbose(verbose);
130 
131 	if ((pw = getpwnam(UNWIND_USER)) == NULL)
132 		fatal("getpwnam");
133 
134 	if (chroot(pw->pw_dir) == -1)
135 		fatal("chroot");
136 	if (chdir("/") == -1)
137 		fatal("chdir(\"/\")");
138 
139 	unwind_process = PROC_FRONTEND;
140 	setproctitle("%s", log_procnames[unwind_process]);
141 	log_procinit(log_procnames[unwind_process]);
142 
143 	if (setgroups(1, &pw->pw_gid) ||
144 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
145 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
146 		fatal("can't drop privileges");
147 
148 	if (pledge("stdio unix recvfd", NULL) == -1)
149 		fatal("pledge");
150 
151 	event_init();
152 
153 	/* Setup signal handler. */
154 	signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL);
155 	signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL);
156 	signal_add(&ev_sigint, NULL);
157 	signal_add(&ev_sigterm, NULL);
158 	signal(SIGPIPE, SIG_IGN);
159 	signal(SIGHUP, SIG_IGN);
160 
161 	/* Setup pipe and event handler to the parent process. */
162 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
163 		fatal(NULL);
164 	imsg_init(&iev_main->ibuf, 3);
165 	iev_main->handler = frontend_dispatch_main;
166 	iev_main->events = EV_READ;
167 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
168 	    iev_main->handler, iev_main);
169 	event_add(&iev_main->ev, NULL);
170 
171 	rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
172 	    CMSG_SPACE(sizeof(int));
173 	if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL)
174 		fatal("malloc");
175 
176 	udp4ev.rcviov[0].iov_base = (caddr_t)udp4ev.query;
177 	udp4ev.rcviov[0].iov_len = sizeof(udp4ev.query);
178 	udp4ev.rcvmhdr.msg_name = (caddr_t)&udp4ev.from;
179 	udp4ev.rcvmhdr.msg_namelen = sizeof(udp4ev.from);
180 	udp4ev.rcvmhdr.msg_iov = udp4ev.rcviov;
181 	udp4ev.rcvmhdr.msg_iovlen = 1;
182 
183 	udp6ev.rcviov[0].iov_base = (caddr_t)udp6ev.query;
184 	udp6ev.rcviov[0].iov_len = sizeof(udp6ev.query);
185 	udp6ev.rcvmhdr.msg_name = (caddr_t)&udp6ev.from;
186 	udp6ev.rcvmhdr.msg_namelen = sizeof(udp6ev.from);
187 	udp6ev.rcvmhdr.msg_iov = udp6ev.rcviov;
188 	udp6ev.rcvmhdr.msg_iovlen = 1;
189 
190 	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
191 	    CMSG_SPACE(sizeof(int));
192 	if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL)
193 		fatal("%s", __func__);
194 
195 	TAILQ_INIT(&pending_queries);
196 
197 	event_dispatch();
198 
199 	frontend_shutdown();
200 }
201 
202 __dead void
203 frontend_shutdown(void)
204 {
205 	/* Close pipes. */
206 	msgbuf_write(&iev_resolver->ibuf.w);
207 	msgbuf_clear(&iev_resolver->ibuf.w);
208 	close(iev_resolver->ibuf.fd);
209 	msgbuf_write(&iev_main->ibuf.w);
210 	msgbuf_clear(&iev_main->ibuf.w);
211 	close(iev_main->ibuf.fd);
212 
213 	config_clear(frontend_conf);
214 
215 	free(iev_resolver);
216 	free(iev_main);
217 
218 	log_info("frontend exiting");
219 	exit(0);
220 }
221 
222 int
223 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
224 {
225 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data,
226 	    datalen));
227 }
228 
229 int
230 frontend_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen)
231 {
232 	return (imsg_compose_event(iev_resolver, type, 0, pid, -1, data,
233 	    datalen));
234 }
235 
236 void
237 frontend_dispatch_main(int fd, short event, void *bula)
238 {
239 	static struct unwind_conf		*nconf;
240 	struct unwind_forwarder		*unwind_forwarder;
241 	struct imsg			 imsg;
242 	struct imsgev			*iev = bula;
243 	struct imsgbuf			*ibuf = &iev->ibuf;
244 	int				 n, shut = 0;
245 
246 	if (event & EV_READ) {
247 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
248 			fatal("imsg_read error");
249 		if (n == 0)	/* Connection closed. */
250 			shut = 1;
251 	}
252 	if (event & EV_WRITE) {
253 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
254 			fatal("msgbuf_write");
255 		if (n == 0)	/* Connection closed. */
256 			shut = 1;
257 	}
258 
259 	for (;;) {
260 		if ((n = imsg_get(ibuf, &imsg)) == -1)
261 			fatal("%s: imsg_get error", __func__);
262 		if (n == 0)	/* No more messages. */
263 			break;
264 
265 		switch (imsg.hdr.type) {
266 		case IMSG_SOCKET_IPC:
267 			/*
268 			 * Setup pipe and event handler to the resolver
269 			 * process.
270 			 */
271 			if (iev_resolver) {
272 				log_warnx("%s: received unexpected imsg fd "
273 				    "to frontend", __func__);
274 				break;
275 			}
276 			if ((fd = imsg.fd) == -1) {
277 				log_warnx("%s: expected to receive imsg fd to "
278 				   "frontend but didn't receive any",
279 				   __func__);
280 				break;
281 			}
282 
283 			iev_resolver = malloc(sizeof(struct imsgev));
284 			if (iev_resolver == NULL)
285 				fatal(NULL);
286 
287 			imsg_init(&iev_resolver->ibuf, fd);
288 			iev_resolver->handler = frontend_dispatch_resolver;
289 			iev_resolver->events = EV_READ;
290 
291 			event_set(&iev_resolver->ev, iev_resolver->ibuf.fd,
292 			iev_resolver->events, iev_resolver->handler, iev_resolver);
293 			event_add(&iev_resolver->ev, NULL);
294 			break;
295 		case IMSG_RECONF_CONF:
296 			if ((nconf = malloc(sizeof(struct unwind_conf))) ==
297 			    NULL)
298 				fatal(NULL);
299 			memcpy(nconf, imsg.data, sizeof(struct unwind_conf));
300 			SIMPLEQ_INIT(&nconf->unwind_forwarder_list);
301 			SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list);
302 			break;
303 		case IMSG_RECONF_FORWARDER:
304 			if ((unwind_forwarder = malloc(sizeof(struct
305 			    unwind_forwarder))) == NULL)
306 				fatal(NULL);
307 			memcpy(unwind_forwarder, imsg.data, sizeof(struct
308 			    unwind_forwarder));
309 			SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list,
310 			    unwind_forwarder, entry);
311 			break;
312 		case IMSG_RECONF_DOT_FORWARDER:
313 			if ((unwind_forwarder = malloc(sizeof(struct
314 			    unwind_forwarder))) == NULL)
315 				fatal(NULL);
316 			memcpy(unwind_forwarder, imsg.data, sizeof(struct
317 			    unwind_forwarder));
318 			SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list,
319 			    unwind_forwarder, entry);
320 			break;
321 		case IMSG_RECONF_END:
322 			merge_config(frontend_conf, nconf);
323 			nconf = NULL;
324 			break;
325 		case IMSG_UDP6SOCK:
326 			if ((udp6sock = imsg.fd) == -1)
327 				fatalx("%s: expected to receive imsg "
328 				    "UDP6 fd but didn't receive any",
329 				    __func__);
330 			event_set(&udp6ev.ev, udp6sock, EV_READ | EV_PERSIST,
331 			    udp_receive, &udp6ev);
332 			event_add(&udp6ev.ev, NULL);
333 			break;
334 		case IMSG_UDP4SOCK:
335 			if ((udp4sock = imsg.fd) == -1)
336 				fatalx("%s: expected to receive imsg "
337 				    "UDP4 fd but didn't receive any",
338 				    __func__);
339 			event_set(&udp4ev.ev, udp4sock, EV_READ | EV_PERSIST,
340 			    udp_receive, &udp4ev);
341 			event_add(&udp4ev.ev, NULL);
342 			break;
343 		case IMSG_ROUTESOCK:
344 			if ((fd = imsg.fd) == -1)
345 				fatalx("%s: expected to receive imsg "
346 				    "routesocket fd but didn't receive any",
347 				    __func__);
348 			routesock = fd;
349 			event_set(&ev_route, fd, EV_READ | EV_PERSIST,
350 			    route_receive, NULL);
351 			break;
352 		case IMSG_STARTUP:
353 			frontend_startup();
354 			break;
355 		case IMSG_CONTROLFD:
356 			if ((fd = imsg.fd) == -1)
357 				fatalx("%s: expected to receive imsg "
358 				    "control fd but didn't receive any",
359 				    __func__);
360 			control_state.fd = fd;
361 			/* Listen on control socket. */
362 			TAILQ_INIT(&ctl_conns);
363 			control_listen();
364 			break;
365 		case IMSG_LEASEFD:
366 			if ((fd = imsg.fd) == -1)
367 				fatalx("%s: expected to receive imsg "
368 				    "dhcp lease fd but didn't receive any",
369 				    __func__);
370 			parse_dhcp_lease(fd);
371 			break;
372 		case IMSG_SHUTDOWN:
373 			frontend_imsg_compose_resolver(IMSG_SHUTDOWN, 0, NULL, 0);
374 			break;
375 		default:
376 			log_debug("%s: error handling imsg %d", __func__,
377 			    imsg.hdr.type);
378 			break;
379 		}
380 		imsg_free(&imsg);
381 	}
382 	if (!shut)
383 		imsg_event_add(iev);
384 	else {
385 		/* This pipe is dead. Remove its event handler. */
386 		event_del(&iev->ev);
387 		event_loopexit(NULL);
388 	}
389 }
390 
391 void
392 frontend_dispatch_resolver(int fd, short event, void *bula)
393 {
394 	static struct pending_query	*pq;
395 	struct imsgev			*iev = bula;
396 	struct imsgbuf			*ibuf = &iev->ibuf;
397 	struct imsg			 imsg;
398 	struct query_imsg		*query_imsg;
399 	int				 n, shut = 0;
400 
401 	if (event & EV_READ) {
402 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
403 			fatal("imsg_read error");
404 		if (n == 0)	/* Connection closed. */
405 			shut = 1;
406 	}
407 	if (event & EV_WRITE) {
408 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
409 			fatal("msgbuf_write");
410 		if (n == 0)	/* Connection closed. */
411 			shut = 1;
412 	}
413 
414 	for (;;) {
415 		if ((n = imsg_get(ibuf, &imsg)) == -1)
416 			fatal("%s: imsg_get error", __func__);
417 		if (n == 0)	/* No more messages. */
418 			break;
419 
420 		switch (imsg.hdr.type) {
421 		case IMSG_SHUTDOWN:
422 			frontend_imsg_compose_main(IMSG_SHUTDOWN, 0, NULL, 0);
423 			break;
424 		case IMSG_ANSWER_HEADER:
425 			/* XX size */
426 			query_imsg = (struct query_imsg *)imsg.data;
427 			if ((pq = find_pending_query(query_imsg->id)) ==
428 			    NULL) {
429 				log_warnx("cannot find pending query %llu",
430 				    query_imsg->id);
431 				break;
432 			}
433 			if (query_imsg->err) {
434 				send_answer(pq, NULL, 0);
435 				pq = NULL;
436 				break;
437 			}
438 			pq->bogus = query_imsg->bogus;
439 			break;
440 		case IMSG_ANSWER:
441 			if (pq == NULL)
442 				fatalx("IMSG_ANSWER without HEADER");
443 			send_answer(pq, imsg.data, imsg.hdr.len -
444 			    IMSG_HEADER_SIZE);
445 			break;
446 		case IMSG_RESOLVER_DOWN:
447 			log_debug("%s: IMSG_RESOLVER_DOWN", __func__);
448 			if (udp4sock != -1) {
449 				event_del(&udp4ev.ev);
450 				close(udp4sock);
451 				udp4sock = -1;
452 			}
453 			if (udp6sock != -1) {
454 				event_del(&udp6ev.ev);
455 				close(udp6sock);
456 				udp6sock = -1;
457 			}
458 			break;
459 		case IMSG_RESOLVER_UP:
460 			log_debug("%s: IMSG_RESOLVER_UP", __func__);
461 			frontend_imsg_compose_main(IMSG_OPEN_PORTS, 0, NULL, 0);
462 			break;
463 		case IMSG_CTL_RESOLVER_INFO:
464 		case IMSG_CTL_RESOLVER_WHY_BOGUS:
465 		case IMSG_CTL_RESOLVER_HISTOGRAM:
466 		case IMSG_CTL_END:
467 			control_imsg_relay(&imsg);
468 			break;
469 		default:
470 			log_debug("%s: error handling imsg %d", __func__,
471 			    imsg.hdr.type);
472 			break;
473 		}
474 		imsg_free(&imsg);
475 	}
476 	if (!shut)
477 		imsg_event_add(iev);
478 	else {
479 		/* This pipe is dead. Remove its event handler. */
480 		event_del(&iev->ev);
481 		event_loopexit(NULL);
482 	}
483 }
484 
485 void
486 frontend_startup(void)
487 {
488 	if (!event_initialized(&ev_route))
489 		fatalx("%s: did not receive a route socket from the main "
490 		    "process", __func__);
491 
492 	event_add(&ev_route, NULL);
493 
494 	frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0);
495 	rtmget_default();
496 }
497 
498 void
499 udp_receive(int fd, short events, void *arg)
500 {
501 	struct udp_ev		*udpev = (struct udp_ev *)arg;
502 	struct pending_query	*pq;
503 	struct query_imsg	*query_imsg;
504 	ssize_t			 len, rem_len, buf_len;
505 	uint16_t		 qdcount, ancount, nscount, arcount, t, c;
506 	uint8_t			*queryp;
507 	char			*str_from, *str, buf[1024], *bufp;
508 
509 	if ((len = recvmsg(fd, &udpev->rcvmhdr, 0)) < 0) {
510 		log_warn("recvmsg");
511 		return;
512 	}
513 
514 	bufp = buf;
515 	buf_len = sizeof(buf);
516 
517 	str_from = ip_port((struct sockaddr *)&udpev->from);
518 
519 	if (len < LDNS_HEADER_SIZE) {
520 		log_warnx("bad query: too short, from: %s", str_from);
521 		return;
522 	}
523 
524 	qdcount = LDNS_QDCOUNT(udpev->query);
525 	ancount = LDNS_ANCOUNT(udpev->query);
526 	nscount = LDNS_NSCOUNT(udpev->query);
527 	arcount = LDNS_ARCOUNT(udpev->query);
528 
529 	if (qdcount != 1 && ancount != 0 && nscount != 0 && arcount != 0) {
530 		log_warnx("invalid query from %s, qdcount: %d, ancount: %d "
531 		    "nscount: %d, arcount: %d", str_from, qdcount, ancount,
532 		    nscount, arcount);
533 		return;
534 	}
535 
536 	log_debug("query from %s", str_from);
537 	if ((str = sldns_wire2str_pkt(udpev->query, len)) != NULL) {
538 		log_debug("%s", str);
539 		free(str);
540 	}
541 
542 	queryp = udpev->query;
543 	rem_len = len;
544 
545 	queryp += LDNS_HEADER_SIZE;
546 	rem_len -= LDNS_HEADER_SIZE;
547 
548 	sldns_wire2str_dname_scan(&queryp, &rem_len, &bufp, &buf_len,
549 	     udpev->query, len);
550 
551 	if (rem_len < 4) {
552 		log_warnx("malformed query");
553 		return;
554 	}
555 
556 	t = sldns_read_uint16(queryp);
557 	c = sldns_read_uint16(queryp+2);
558 	queryp += 4;
559 	rem_len -= 4;
560 
561 	if ((pq = malloc(sizeof(*pq))) == NULL) {
562 		log_warn(NULL);
563 		return;
564 	}
565 
566 	if ((pq->query = malloc(len)) == NULL) {
567 		log_warn(NULL);
568 		free(pq);
569 		return;
570 	}
571 
572 	do {
573 		arc4random_buf(&pq->imsg_id, sizeof(pq->imsg_id));
574 	} while(find_pending_query(pq->imsg_id) != NULL);
575 
576 	memcpy(pq->query, udpev->query, len);
577 	pq->len = len;
578 	pq->from = udpev->from;
579 	pq->fd = fd;
580 
581 	if ((query_imsg = calloc(1, sizeof(*query_imsg))) == NULL) {
582 		log_warn(NULL);
583 		return;
584 	}
585 
586 	if (strlcpy(query_imsg->qname, buf, sizeof(query_imsg->qname)) >=
587 	    sizeof(buf)) {
588 		log_warnx("qname too long");
589 		free(query_imsg);
590 		/* XXX SERVFAIL */
591 		free(pq->query);
592 		free(pq);
593 		return;
594 	}
595 	query_imsg->id = pq->imsg_id;
596 	query_imsg->t = t;
597 	query_imsg->c = c;
598 
599 	if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, query_imsg,
600 	    sizeof(*query_imsg)) != -1) {
601 		TAILQ_INSERT_TAIL(&pending_queries, pq, entry);
602 	} else {
603 		free(query_imsg);
604 		/* XXX SERVFAIL */
605 		free(pq->query);
606 		free(pq);
607 	}
608 
609 }
610 
611 void
612 send_answer(struct pending_query *pq, uint8_t *answer, ssize_t len)
613 {
614 	log_debug("result for %s",
615 	    ip_port((struct sockaddr*)&pq->from));
616 
617 	if (answer == NULL) {
618 		answer = pq->query;
619 		len = pq->len;
620 
621 		LDNS_QR_SET(answer);
622 		LDNS_RA_SET(answer);
623 		LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL);
624 	} else {
625 		if (pq->bogus) {
626 			if(LDNS_CD_WIRE(pq->query)) {
627 				LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query));
628 				LDNS_CD_SET(answer);
629 			} else {
630 				answer = pq->query;
631 				len = pq->len;
632 
633 				LDNS_QR_SET(answer);
634 				LDNS_RA_SET(answer);
635 				LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL);
636 			}
637 		} else {
638 			LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query));
639 		}
640 	}
641 
642 	if(sendto(pq->fd, answer, len, 0, (struct sockaddr *)
643 	   &pq->from, pq->from.ss_len) == -1)
644 		log_warn("sendto");
645 
646 	TAILQ_REMOVE(&pending_queries, pq, entry);
647 	free(pq->query);
648 	free(pq);
649 }
650 
651 char*
652 ip_port(struct sockaddr *sa)
653 {
654 	static char	 hbuf[NI_MAXHOST], buf[NI_MAXHOST];
655 
656 	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
657 	    NI_NUMERICHOST) != 0) {
658 		snprintf(buf, sizeof(buf), "%s", "(unknown)");
659 		return buf;
660 	}
661 
662 	if (sa->sa_family == AF_INET6)
663 		snprintf(buf, sizeof(buf), "[%s]:%d", hbuf,
664 		    ((struct sockaddr_in6 *)sa)->sin6_port);
665 	if (sa->sa_family == AF_INET)
666 		snprintf(buf, sizeof(buf), "[%s]:%d", hbuf,
667 		    ((struct sockaddr_in *)sa)->sin_port);
668 
669 	return buf;
670 }
671 
672 struct pending_query*
673 find_pending_query(uint64_t id)
674 {
675 	struct pending_query	*pq;
676 
677 	TAILQ_FOREACH(pq, &pending_queries, entry)
678 		if (pq->imsg_id == id)
679 			return pq;
680 	return NULL;
681 }
682 
683 void
684 route_receive(int fd, short events, void *arg)
685 {
686 	static uint8_t			 *buf;
687 
688 	struct rt_msghdr		*rtm;
689 	struct sockaddr			*sa, *rti_info[RTAX_MAX];
690 	ssize_t				 n;
691 
692 	if (buf == NULL) {
693 		buf = malloc(ROUTE_SOCKET_BUF_SIZE);
694 		if (buf == NULL)
695 			fatal("malloc");
696 	}
697 	rtm = (struct rt_msghdr *)buf;
698 	if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) {
699 		if (errno == EAGAIN || errno == EINTR)
700 			return;
701 		log_warn("dispatch_rtmsg: read error");
702 		return;
703 	}
704 
705 	if (n == 0)
706 		fatal("routing socket closed");
707 
708 	if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
709 		log_warnx("partial rtm of %zd in buffer", n);
710 		return;
711 	}
712 
713 	if (rtm->rtm_version != RTM_VERSION)
714 		return;
715 
716 	sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
717 	get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
718 
719 	handle_route_message(rtm, rti_info);
720 }
721 
722 #define ROUNDUP(a) \
723 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
724 
725 void
726 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
727 {
728 	int	i;
729 
730 	for (i = 0; i < RTAX_MAX; i++) {
731 		if (addrs & (1 << i)) {
732 			rti_info[i] = sa;
733 			sa = (struct sockaddr *)((char *)(sa) +
734 			    ROUNDUP(sa->sa_len));
735 		} else
736 			rti_info[i] = NULL;
737 	}
738 }
739 
740 void
741 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
742 {
743 	char	buf[IF_NAMESIZE], *bufp;
744 
745 	switch (rtm->rtm_type) {
746 	case RTM_GET:
747 		if (rtm->rtm_errno != 0)
748 			break;
749 		if (!(rtm->rtm_flags & RTF_UP))
750 			break;
751 		if (!(rtm->rtm_addrs & RTA_DST))
752 			break;
753 		if (rti_info[RTAX_DST]->sa_family != AF_INET)
754 			break;
755 		if (((struct sockaddr_in *)rti_info[RTAX_DST])->sin_addr.
756 		    s_addr != INADDR_ANY)
757 			break;
758 		if (!(rtm->rtm_addrs & RTA_NETMASK))
759 			break;
760 		if (rti_info[RTAX_NETMASK]->sa_family != AF_INET)
761 			break;
762 		if (((struct sockaddr_in *)rti_info[RTAX_NETMASK])->sin_addr.
763 		    s_addr != INADDR_ANY)
764 			break;
765 
766 		frontend_imsg_compose_main(IMSG_OPEN_DHCP_LEASE, 0,
767 		    &rtm->rtm_index, sizeof(rtm->rtm_index));
768 
769 		bufp = if_indextoname(rtm->rtm_index, buf);
770 		if (bufp)
771 			log_debug("default route is on %s", buf);
772 
773 		break;
774 	default:
775 		break;
776 	}
777 
778 }
779 
780 void
781 rtmget_default(void)
782 {
783 	static int		 rtm_seq;
784 	struct rt_msghdr	 rtm;
785 	struct sockaddr_in	 sin;
786 	struct iovec		 iov[5];
787 	long			 pad = 0;
788 	int			 iovcnt = 0, padlen;
789 
790 	memset(&sin, 0, sizeof(sin));
791 	sin.sin_family = AF_INET;
792 	sin.sin_len = sizeof(sin);
793 
794 	memset(&rtm, 0, sizeof(rtm));
795 
796 	rtm.rtm_version = RTM_VERSION;
797 	rtm.rtm_type = RTM_GET;
798 	rtm.rtm_msglen = sizeof(rtm);
799 	rtm.rtm_tableid = 0; /* XXX imsg->rdomain; */
800 	rtm.rtm_seq = ++rtm_seq;
801 	rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
802 
803 	iov[iovcnt].iov_base = &rtm;
804 	iov[iovcnt++].iov_len = sizeof(rtm);
805 
806 	/* dst */
807 	iov[iovcnt].iov_base = &sin;
808 	iov[iovcnt++].iov_len = sizeof(sin);
809 	rtm.rtm_msglen += sizeof(sin);
810 	padlen = ROUNDUP(sizeof(sin)) - sizeof(sin);
811 	if (padlen > 0) {
812 		iov[iovcnt].iov_base = &pad;
813 		iov[iovcnt++].iov_len = padlen;
814 		rtm.rtm_msglen += padlen;
815 	}
816 
817 	/* mask */
818 	iov[iovcnt].iov_base = &sin;
819 	iov[iovcnt++].iov_len = sizeof(sin);
820 	rtm.rtm_msglen += sizeof(sin);
821 	padlen = ROUNDUP(sizeof(sin)) - sizeof(sin);
822 	if (padlen > 0) {
823 		iov[iovcnt].iov_base = &pad;
824 		iov[iovcnt++].iov_len = padlen;
825 		rtm.rtm_msglen += padlen;
826 	}
827 
828 	if (writev(routesock, iov, iovcnt) == -1)
829 		log_warn("failed to send route message");
830 }
831 
832 void
833 parse_dhcp_lease(int fd)
834 {
835 	FILE	*f;
836 	char	*line = NULL, *cur_ns = NULL, *ns = NULL;
837 	size_t	 linesize = 0;
838 	ssize_t	 linelen;
839 	time_t	 epoch, lease_time, now;
840 	char **tok, *toks[4], *p;
841 
842 	if((f = fdopen(fd, "r")) == NULL) {
843 		log_warn("cannot read dhcp lease");
844 		close(fd);
845 		return;
846 	}
847 
848 	now = time(NULL);
849 
850 	while ((linelen = getline(&line, &linesize, f)) != -1) {
851 		for (tok = toks; tok < &toks[3] && (*tok = strsep(&line, " \t"))
852 		    != NULL;) {
853 			if (**tok != '\0')
854 				tok++;
855 		}
856 		*tok = NULL;
857 		if (strcmp(toks[0], "option") == 0) {
858 			if (strcmp(toks[1], "domain-name-servers") == 0) {
859 				if((p = strchr(toks[2], ';')) != NULL) {
860 					*p='\0';
861 					cur_ns = strdup(toks[2]);
862 				}
863 			}
864 			if (strcmp(toks[1], "dhcp-lease-time") == 0) {
865 				if((p = strchr(toks[2], ';')) != NULL) {
866 					*p='\0';
867 					lease_time = strtonum(toks[2], 0,
868 					    INT64_MAX, NULL);
869 				}
870 			}
871 		} else if (strcmp(toks[0], "epoch") == 0) {
872 			if((p = strchr(toks[1], ';')) != NULL) {
873 				*p='\0';
874 				epoch = strtonum(toks[1], 0,
875 				    INT64_MAX, NULL);
876 			}
877 		}
878 		else if (*toks[0] == '}') {
879 			if (epoch + lease_time > now ) {
880 				free(ns);
881 				ns = cur_ns;
882 				//log_debug("ns: %s, lease_time: %lld, epoch: "
883 				//    "%lld\n", cur_ns, lease_time, epoch);
884 			} else /* expired lease */
885 				free(cur_ns);
886 		}
887 	}
888 	free(line);
889 
890 	if (ferror(f))
891 		log_warn("getline");
892 	fclose(f);
893 
894 	if (ns != NULL) {
895 		log_debug("%s: ns: %s", __func__, ns);
896 		frontend_imsg_compose_resolver(IMSG_FORWARDER, 0, ns,
897 		    strlen(ns) + 1);
898 	}
899 }
900