1 /*
2  * Copyright (c) 2010 Christiano F. Haesbaert <haesbaert@haesbaert.org>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /*
18  * This file needs a refactoring, pkt_parse and serialize functions rely on
19  * pktcomp being always accurate, most of functions here are not re-entrant and
20  * depend on state that they shouldn't, like serialize_dname which must have the
21  * current packet buffer as input. Also, name compression uses a different
22  * logic when receiving/sending, they should be made equal.
23  * I'll rewrite all of it when I have the time.
24  */
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/queue.h>
28 #include <sys/uio.h>
29 
30 #include <netinet/in.h>
31 #include <netinet/in_systm.h>
32 #include <netinet/ip.h>
33 #include <netinet/udp.h>
34 #include <arpa/inet.h>
35 #include <arpa/nameser.h>
36 
37 #include <net/if_dl.h>
38 
39 #include <errno.h>
40 #include <event.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "mdnsd.h"
45 #include "log.h"
46 
47 #define CACHEFLUSH_MSK	0x8000
48 #define CLASS_MSK	~0x8000
49 #define UNIRESP_MSK	0x8000
50 #define NAMECOMP_BYTE_MSK 0xc0	/* TODO unify this someday */
51 #define NAMECOMP_MSK	0xc000
52 #define NAMEADDR_MSK	~0xc000
53 #define MAXLABELS	128
54 #define MAXPACKET	10000
55 #define HDR_LEN		12
56 #define MINQRY_LEN	6 /* 4 (qtype + qclass) +1 (null) + 1 (label len) */
57 /* Defer truncated packets from 400ms-500ms */
58 #define RANDOM_DEFERTIME			\
59 	(arc4random_uniform((u_int32_t) 100000)	\
60 	    + 400000)
61 
62 int		 pkt_parse_header(u_int8_t **, u_int16_t *, struct pkt *);
63 ssize_t		 pkt_parse_dname(u_int8_t *, u_int16_t, char [MAXHOSTNAMELEN]);
64 int		 pkt_parse_rr(u_int8_t **, u_int16_t *, struct rr *);
65 int		 pkt_parse_question(u_int8_t **, u_int16_t *, struct pkt *);
66 int		 pkt_handle_qst(struct pkt *);
67 ssize_t		 serialize_rr(struct rr *, u_int8_t *, u_int16_t);
68 ssize_t		 serialize_qst(struct question *, u_int8_t *, u_int16_t);
69 ssize_t		 serialize_dname(u_int8_t *, u_int16_t, char [MAXHOSTNAMELEN], int);
70 ssize_t		 serialize_rdata(struct rr *, u_int8_t *, u_int16_t);
71 int		 rr_parse_dname(u_int8_t *, u_int16_t, char [MAXHOSTNAMELEN]);
72 ssize_t		 charstr(char [MAXCHARSTR], u_int8_t *, u_int16_t);
73 void		 header_htons(HEADER *);
74 void		 header_ntohs(HEADER *);
75 int		 pktcomp_add(char [MAXHOSTNAMELEN], u_int16_t);
76 struct namecomp *pktcomp_lookup(char [MAXHOSTNAMELEN]);
77 
78 extern struct mdnsd_conf *conf;
79 
80 /* Used in name compression */
81 struct namecomp {
82 	LIST_ENTRY(namecomp)	entry;
83 	char			dname[MAXHOSTNAMELEN];
84 	u_int16_t		offset;
85 };
86 
87 struct {
88 	LIST_HEAD(, namecomp)	namecomp_list;
89 	u_int8_t		*start;
90 	u_int16_t		len;
91 } pktcomp;
92 
93 /* Deferred packets, Known Answer Supression packets with TC bit */
94 TAILQ_HEAD(, pkt) deferred_queue;
95 
96 void
packet_init(void)97 packet_init(void)
98 {
99 	LIST_INIT(&pktcomp.namecomp_list);
100 	TAILQ_INIT(&deferred_queue);
101 }
102 
103 /* Send and receive packets */
104 int
send_packet(struct iface * iface,void * pkt,size_t len,struct sockaddr_in * dst)105 send_packet(struct iface *iface, void *pkt, size_t len, struct sockaddr_in *dst)
106 {
107 	/* set outgoing interface for multicast traffic */
108 	if (IN_MULTICAST(ntohl(dst->sin_addr.s_addr)))
109 		if (if_set_mcast(iface) == -1) {
110 			log_warn("send_packet: error setting multicast "
111 			    "interface, %s", iface->name);
112 			return (-1);
113 		}
114 
115 	if (sendto(iface->fd, pkt, len, 0,
116 	    (struct sockaddr *)dst, sizeof(*dst)) == -1) {
117 		log_warn("send_packet: error sending packet on interface "
118 			 "%s, len %zd", iface->name, len);
119 		return (-1);
120 	}
121 
122 	return (0);
123 }
124 
125 void
recv_packet(int fd,short event,void * bula)126 recv_packet(int fd, short event, void *bula)
127 {
128 	union {
129 		struct cmsghdr hdr;
130 		char	buf[CMSG_SPACE(sizeof(struct sockaddr_dl)) +
131 		    CMSG_SPACE(sizeof(struct in_addr))];
132 	} cmsgbuf;
133 	struct sockaddr_in	 ipsrc;
134 	struct in_addr		 ipdst, mdns_addr;
135 	struct iovec		 iov;
136 	struct msghdr		 msg;
137 	struct cmsghdr		*cmsg;
138 	struct sockaddr_dl	*dst = NULL;
139 	struct iface		*iface;
140 	static u_int8_t		 buf[MAXPACKET];
141 	struct rr		*rr;
142 	struct pkt		*pkt;
143 	struct timeval		 tv;
144 	u_int8_t		*pbuf;
145 	u_int16_t		 i, len;
146 	ssize_t			 r;
147 
148 	if (event != EV_READ)
149 		return;
150 
151 	inet_aton(ALL_MDNS_DEVICES, &mdns_addr);
152 	bzero(&msg, sizeof(msg));
153 	bzero(buf, sizeof(buf));
154 	bzero(&ipdst, sizeof(ipdst));
155 	pbuf = buf;
156 
157 	iov.iov_base = buf;
158 	iov.iov_len = MAXPACKET;
159 	msg.msg_name = &ipsrc;
160 	msg.msg_namelen = sizeof(ipsrc);
161 	msg.msg_iov = &iov;
162 	msg.msg_iovlen = 1;
163 	msg.msg_control = &cmsgbuf.buf;
164 	msg.msg_controllen = sizeof(cmsgbuf.buf);
165 
166 	if ((r = recvmsg(fd, &msg, 0)) == -1) {
167 		if (errno != EINTR && errno != EAGAIN)
168 			log_warn("recv_packet: read error: %s",
169 			    strerror(errno));
170 		return;
171 	}
172 
173 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
174 	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
175 		if (cmsg->cmsg_level == IPPROTO_IP &&
176 		    cmsg->cmsg_type == IP_RECVIF) {
177 			dst = (struct sockaddr_dl *)CMSG_DATA(cmsg);
178 			continue;
179 		}
180 		if (cmsg->cmsg_level == IPPROTO_IP &&
181 		    cmsg->cmsg_type == IP_RECVDSTADDR) {
182 			ipdst = *(struct in_addr *)CMSG_DATA(cmsg);
183 			continue;
184 		}
185 
186 	}
187 	/*
188 	 * We need a valid dst to lookup receiving interface, see below.
189 	 * Ipdst must be filled so we can check for unicast answers, see below.
190 	 */
191 	if (dst == NULL || ipdst.s_addr == 0)
192 		return;
193 
194 	len = (u_int16_t)r;
195 
196 	/* Check the packet is not from one of the local interfaces */
197 	LIST_FOREACH(iface, &conf->iface_list, entry)
198 		if (iface->addr.s_addr == ipsrc.sin_addr.s_addr)
199 			return;
200 
201 	if ((pkt = calloc(1, sizeof(*pkt))) == NULL)
202 		fatal("calloc");
203 	pkt_init(pkt);
204 	pktcomp_reset(0, buf, len);
205 	pkt->ipsrc = ipsrc;
206 	/*
207 	 * Parse header, we'll use the HEADER structure in nameser.h
208 	 */
209 	if (pkt_parse_header(&pbuf, &len, pkt) == -1) {
210 		pkt_cleanup(pkt);
211 		free(pkt);
212 		return;
213 	}
214 
215 	/*
216 	 * Multicastdns draft 4. Source Address check.
217 	 * If a response packet was sent to an unicast address, check if the
218 	 * source ip address in the packet matches one of our subnets, if not,
219 	 * drop it.
220 	 */
221 	if (pkt->h.qr == MDNS_RESPONSE && ipdst.s_addr != mdns_addr.s_addr) {
222 		/* if_find_iface will try to match source address */
223 		if ((iface = if_find_iface(dst->sdl_index,
224 		    pkt->ipsrc.sin_addr)) == NULL) {
225 			log_warn("recv_packet: "
226 			    "cannot find a matching interface (1)");
227 			pkt_cleanup(pkt);
228 			free(pkt);
229 			return;
230 		}
231 	}
232 	else /* Disregard source ip address, just find a matching iface */
233 		if ((iface = if_find_index(dst->sdl_index)) == NULL) {
234 			log_warn("recv_packet: "
235 			    "cannot find a matching interface (2)");
236 			pkt_cleanup(pkt);
237 			free(pkt);
238 			return;
239 		}
240 	/* Save the received interface */
241 	pkt->iface = iface;
242 
243 	/* Check if this is a legacy dns packet */
244 	if (ntohs(pkt->ipsrc.sin_port) != MDNS_PORT)
245 		pkt->flags |= PKT_FLAG_LEGACY;
246 
247 	/* Parse question section */
248 	if (pkt->h.qr == MDNS_QUERY)
249 		for (i = 0; i < pkt->h.qdcount; i++)
250 			if (pkt_parse_question(&pbuf, &len, pkt) == -1) {
251 				pkt_cleanup(pkt);
252 				free(pkt);
253 				return;
254 			}
255 	/* Parse RR sections */
256 	for (i = 0; i < pkt->h.ancount; i++) {
257 		if ((rr = calloc(1, sizeof(*rr))) == NULL)
258 			fatal("calloc");
259 		if (pkt_parse_rr(&pbuf, &len, rr) == -1) {
260 			log_warnx("Can't parse AN RR");
261 			free(rr);
262 			pkt_cleanup(pkt);
263 			free(pkt);
264 			return;
265 		}
266 		LIST_INSERT_HEAD(&pkt->anlist, rr, pentry);
267 	}
268 	for (i = 0; i < pkt->h.nscount; i++) {
269 		if ((rr = calloc(1, sizeof(*rr))) == NULL)
270 			fatal("calloc");
271 		if (pkt_parse_rr(&pbuf, &len, rr) == -1) {
272 			log_warnx("Can't parse NS RR");
273 			free(rr);
274 			pkt_cleanup(pkt);
275 			free(pkt);
276 			return;
277 		}
278 		LIST_INSERT_HEAD(&pkt->nslist, rr, pentry);
279 	}
280 	for (i = 0; i < pkt->h.arcount; i++) {
281 		if ((rr = calloc(1, sizeof(*rr))) == NULL)
282 			fatal("calloc");
283 		if (pkt_parse_rr(&pbuf, &len, rr) == -1) {
284 			log_warnx("Can't parse AR RR");
285 			free(rr);
286 			pkt_cleanup(pkt);
287 			free(pkt);
288 			return;
289 		}
290 
291 		LIST_INSERT_HEAD(&pkt->arlist, rr, pentry);
292 	}
293 
294 	/* XXX: If we droped an RR our packet counts may be wrong. */
295 
296 	if (len != 0) {
297 		log_warnx("Couldn't read all packet, %u bytes left", len);
298 		log_warnx("ancount %d, nscount %d, arcount %d",
299 		    pkt->h.ancount, pkt->h.nscount, pkt->h.arcount);
300 		pkt_cleanup(pkt);
301 		free(pkt);
302 		return;
303 	}
304 
305 	/*
306 	 * Packet parsing done, our pkt structure is complete.
307 	 */
308 
309 	/*
310 	 * Check if the packet is the continuation of a previous truncated
311 	 * packet, see below. A query packet with no questions and with answers
312 	 * in is a continuation. Merge this answer with the previous packet.
313 	 */
314 	evtimer_set(&pkt->timer, pkt_process, pkt);
315 	if (pkt->h.qr == MDNS_QUERY &&
316 	    pkt->h.qdcount == 0 && pkt->h.arcount == 0 &&
317 	    pkt->h.nscount == 0 && pkt->h.ancount > 0) {
318 		struct pkt *dpkt, *match = NULL;
319 
320 		TAILQ_FOREACH(dpkt, &deferred_queue, entry) {
321 			/* XXX: Should we compare source port as well ? */
322 			if (dpkt->ipsrc.sin_addr.s_addr !=
323 			    pkt->ipsrc.sin_addr.s_addr)
324 				continue;
325 			/* Found a match */
326 			match = dpkt;
327 			break;
328 		}
329 		if (match != NULL) {
330 			if (evtimer_pending(&match->timer, NULL))
331 				evtimer_del(&match->timer);
332 			TAILQ_REMOVE(&deferred_queue, match, entry);
333 			/* Merge pkt into match */
334 			while ((rr = LIST_FIRST(&pkt->anlist)) != NULL) {
335 				LIST_REMOVE(rr, pentry);
336 				pkt->h.ancount--;
337 				pkt_add_anrr(match, rr);
338 			}
339 			pkt_cleanup(pkt);
340 			free(pkt);
341 			pkt = match;
342 		}
343 		else
344 			log_warnx("Got a continuation packet from %s:%s "
345 			    "but no match", inet_ntoa(pkt->ipsrc.sin_addr),
346 			    ntohs(pkt->ipsrc.sin_port));
347 	}
348 
349 	/*
350 	 * Mdns Draft 7.2 Multi-Packet Known Answer Supression
351 	 * A Multicast DNS Responder seeing a Multicast DNS Query with the TC
352 	 * bit set defers its response for a time period randomly selected in
353 	 * the interval 400-500ms. This gives the Multicast DNS Querier time to
354 	 * send additional Known Answer packets before the Responder responds.
355 	 * If the Responder sees any of its answers listed in the Known Answer
356 	 * lists of subsequent packets from the querying host, it SHOULD delete
357 	 * that answer from the list of answers it is planning to give, provided
358 	 * that no other host on the network is also waiting to receive the same
359 	 * answer record.  Check if this packet was truncated, due to too many
360 	 * Known Answer Supression entries, if so, defer processing
361 	 */
362 
363 	if (pkt->h.qr == MDNS_QUERY && pkt->h.tc) {
364 		TAILQ_INSERT_TAIL(&deferred_queue, pkt, entry);
365 		timerclear(&tv);
366 		tv.tv_usec = RANDOM_DEFERTIME;
367 		evtimer_add(&pkt->timer, &tv);
368 		return;
369 	}
370 
371 	/* Use 0 as event as our processing wasn't deferred */
372 	pkt_process(-1, 0, pkt);
373 }
374 
375 void
pkt_process(int unused,short event,void * v_pkt)376 pkt_process(int unused, short event, void *v_pkt)
377 {
378 	struct pkt	*pkt = v_pkt;
379 	struct rr	*rr, *rraux;
380 
381 	if (event == EV_TIMEOUT) {
382 		log_debug("pkt deferred from %s:%u",
383 		    inet_ntoa(pkt->ipsrc.sin_addr), ntohs(pkt->ipsrc.sin_port));
384 		TAILQ_REMOVE(&deferred_queue, pkt, entry);
385 	}
386 
387 	/* Process all answers */
388 	/*
389 	 * The answer section for query packets is not authoritative,
390 	 * it's used in known answer supression, so, if it's a query,
391 	 * discard all answers.
392 	 */
393 	switch (pkt->h.qr) {
394 	case MDNS_QUERY:
395 		if (pkt_handle_qst(pkt) == -1) {
396 			log_warnx("pkt_handle_qst error");
397 			goto bad;
398 		}
399 		/* Clear all answer section (KNA) */
400 		while((rr = LIST_FIRST(&pkt->anlist)) != NULL) {
401 			LIST_REMOVE(rr, pentry);
402 			free(rr);
403 		}
404 		/* Clear up ESDN0/T_opt packets */
405 		LIST_FOREACH_SAFE(rr, &pkt->arlist, pentry, rraux) {
406 			if (rr->rrs.type == T_OPT) {
407 				LIST_REMOVE(rr, pentry);
408 				free(rr);
409 			}
410 		}
411 
412 		break;
413 	case MDNS_RESPONSE:
414 		/* Process answer section */
415 		while ((rr = LIST_FIRST(&pkt->anlist)) != NULL) {
416 			LIST_REMOVE(rr, pentry);
417 			cache_process(rr);
418 		}
419 		/* Process additional section */
420 		while ((rr = LIST_FIRST(&pkt->arlist)) != NULL) {
421 			LIST_REMOVE(rr, pentry);
422 			cache_process(rr);
423 		}
424 		break;
425 	}
426 
427 	/* Clear all authority section */
428 	while((rr = LIST_FIRST(&pkt->nslist)) != NULL) {
429 		LIST_REMOVE(rr, pentry);
430 		free(rr);
431 	}
432 
433 	/* Sanity check, every section must be empty. */
434 	if (!LIST_EMPTY(&pkt->qlist))
435 		log_warnx("Unprocessed question in Question Section");
436 	if (!LIST_EMPTY(&pkt->anlist))
437 		log_warnx("Unprocessed rr in Answer Section");
438 	if (!LIST_EMPTY(&pkt->nslist))
439 		log_warnx("Unprocessed rr in Authority Section");
440 	if (!LIST_EMPTY(&pkt->arlist))
441 		log_warnx("Unprocessed rr in Additional Section");
442 bad:
443 	pkt_cleanup(pkt);
444 	free(pkt);
445 
446 }
447 
448 int
pkt_sendto(struct pkt * pkt,struct iface * iface,struct sockaddr_in * pdst)449 pkt_sendto(struct pkt *pkt, struct iface *iface, struct sockaddr_in *pdst)
450 {
451 	struct sockaddr_in	 all_mdns;
452 	static u_int8_t		 buf[MAXPACKET];
453 	struct question		*qst;
454 	struct rr		*rr;
455 	HEADER			*h;
456 	u_int8_t		*pbuf;
457 	ssize_t			 n, left;
458 	int 			 inaddrany;
459 
460 	inet_aton(ALL_MDNS_DEVICES, &all_mdns.sin_addr);
461 	all_mdns.sin_port   = htons(MDNS_PORT);
462 	all_mdns.sin_family = AF_INET;
463 	all_mdns.sin_len    = sizeof(struct sockaddr_in);
464 
465 	/* If dst not specified, send to mcast addr */
466 	if (pdst == NULL)
467 		pdst = &all_mdns;
468 	if (iface->mtu > MAXPACKET) {
469 		log_warnx("pkt_sendto: insane mtu");
470 		return (-1);
471 	}
472 	bzero(buf, sizeof(buf));
473 	left = iface->mtu - 28;
474 	h    = (HEADER *) buf;
475 	pbuf = buf;
476 	pktcomp_reset(0, buf, left);
477 	/*
478 	 * Every packet must have a header, we assume pkt_sendto will only be
479 	 * called for full packets, that is, packets that require a header.
480 	 */
481 	if (left < HDR_LEN) {
482 		log_warnx("pkt_sendto: left < HDR_LEN");
483 		return (-1);
484 	}
485 	/* Copy header, field by field as we do our own calculations in
486 	 * qdcount, ancount and etc... */
487 	if (pkt->flags & PKT_FLAG_LEGACY) {
488 		h->id = pkt->h.id;
489 		h->aa = 1;
490 	}
491 	h->qr  = pkt->h.qr;
492 	left  -= HDR_LEN;
493 	pbuf  += HDR_LEN;
494 	/* Append all questions, they must fit a single packet. */
495 	LIST_FOREACH(qst, &pkt->qlist, entry) {
496 		n = serialize_qst(qst, pbuf, left);
497 		if (n == -1 || n > left) {
498 			log_warnx("pkt_sendto: "
499 			    "can't serialize question section");
500 			return (-1);
501 		}
502 		h->qdcount++;
503 		pbuf += n;
504 		left -= n;
505 	}
506 	/*
507 	 * This is where the shit happens, if we are querying and our known
508 	 * answers section won't fit in a single packet, we fragment. The
509 	 * following could be a recursive call, passing a flag telling us if
510 	 * we're in a "fragmented" state or not, but if so, we would need to
511 	 * make buf non-static, allocating MAX_PACKET for each fragmenting
512 	 * packet. This might seem like premature optimization but it's also
513 	 * easier to maintain.
514 	 */
515 	LIST_FOREACH(rr, &pkt->anlist, pentry) {
516 		int in_retry;
517 
518 		in_retry = 0;
519 	retry:
520 		/*
521 		 * Have to patch T_A if INADDR_ANY with the correct interface
522 		 * address.
523 		 */
524 		inaddrany = RR_INADDRANY(rr);
525 		if (inaddrany)
526 			rr->rdata.A.s_addr = iface->addr.s_addr;
527 		n = serialize_rr(rr, pbuf, left);
528 		if (inaddrany)
529 			rr->rdata.A.s_addr = INADDR_ANY;
530 		/* Unexpected n */
531 		if (n > left) {
532 			log_warnx("No space left on packet for an section.");
533 			return (-1);
534 		}
535 		/*
536 		 * Fragmentation only for queries, on answer is an
537 		 * error, actually only for queries with known answer
538 		 * supression.
539 		 */
540 		if (n == -1 && h->qr == MDNS_RESPONSE) {
541 			log_warnx("Can't fragment for response packets");
542 			return (-1);
543 		}
544 		/*
545 		 * Won't fit, send what we have, restart the ball.
546 		 */
547 		if (n == -1) {
548 			/* Set truncation bit and close packet */
549 			h->tc = 1;
550 			header_htons(h);
551 			if (send_packet(iface, buf, pbuf - buf, pdst) == -1)
552 				return (-1);
553 			/* Reset states */
554 			bzero(buf, sizeof(buf));
555 			left = iface->mtu;
556 			pbuf = buf;
557 			/* XXX: alignment bug? */
558 			h    = (HEADER *) buf;
559 			n    = 0;
560 			pktcomp_reset(0, buf, left);
561 			/* Copy header */
562 			if (pkt->flags & PKT_FLAG_LEGACY)
563 				h->id = pkt->h.id;
564 			h->qr  = pkt->h.qr;
565 			left  -= HDR_LEN;
566 			pbuf  += HDR_LEN;
567 			/* Avoid a possible stupid infinite loop */
568 			if (in_retry) {
569 				log_warnx("pkt_sendto: failing on retry");
570 				return (-1);
571 			}
572 			in_retry = 1;
573 			goto retry;
574 		}
575 		h->ancount++;
576 		pbuf += n;
577 		left -= n;
578 	}
579 
580 	/* Append all authorities, they must fit a single packet. */
581 	LIST_FOREACH(rr, &pkt->nslist, pentry) {
582 		inaddrany = RR_INADDRANY(rr);
583 		if (inaddrany)
584 			rr->rdata.A.s_addr = iface->addr.s_addr;
585 		n = serialize_rr(rr, pbuf, left);
586 		if (inaddrany)
587 			rr->rdata.A.s_addr = INADDR_ANY;
588 		if (n == -1 || n > left) {
589 			return (-1);
590 		}
591 		h->nscount++;
592 		pbuf += n;
593 		left -= n;
594 	}
595 
596 	/* Append all additionals, they must fit a single packet. */
597 	LIST_FOREACH(rr, &pkt->arlist, pentry) {
598 		inaddrany = RR_INADDRANY(rr);
599 		if (inaddrany)
600 			rr->rdata.A.s_addr = iface->addr.s_addr;
601 		n = serialize_rr(rr, pbuf, left);
602 		if (inaddrany)
603 			rr->rdata.A.s_addr = INADDR_ANY;
604 		if (n == -1 || n > left) {
605 			return (-1);
606 		}
607 		h->arcount++;
608 		pbuf += n;
609 		left -= n;
610 	}
611 
612 	/* Close packet and send. */
613 	header_htons(h);
614 	if (send_packet(iface, buf, pbuf - buf, pdst) == -1)
615 		return (-1);
616 	return (0);
617 }
618 
619 int
pkt_send(struct pkt * pkt,struct iface * iface)620 pkt_send(struct pkt *pkt, struct iface *iface)
621 {
622 	struct iface	*iface2;
623 	int		 succ = 0;
624 
625 	if (iface != ALL_IFACE)
626 		return (pkt_sendto(pkt, iface, NULL));
627 
628 	LIST_FOREACH(iface2, &conf->iface_list, entry) {
629 		if (iface2->state != IF_STA_ACTIVE)
630 			continue;
631 		if (pkt_sendto(pkt, iface2, NULL) == -1)
632 			log_warnx("Can't send packet through %s", iface2->name);
633 		else
634 			succ++;
635 	}
636 	/* If we couldn't send to a single iface, consider an error */
637 	if (succ == 0)
638 		return (-1);
639 
640 	return (0);
641 }
642 
643 void
pkt_init(struct pkt * pkt)644 pkt_init(struct pkt *pkt)
645 {
646 	bzero(pkt, sizeof(*pkt));
647 	LIST_INIT(&pkt->qlist);
648 	LIST_INIT(&pkt->anlist);
649 	LIST_INIT(&pkt->nslist);
650 	LIST_INIT(&pkt->arlist);
651 }
652 
653 void
pkt_cleanup(struct pkt * pkt)654 pkt_cleanup(struct pkt *pkt)
655 {
656 	struct rr	*rr;
657 	struct question *qst;
658 
659 	while ((qst = LIST_FIRST(&pkt->qlist)) != NULL) {
660 		LIST_REMOVE(qst, entry);
661 		free(qst);
662 	}
663 	while ((rr = LIST_FIRST(&pkt->anlist)) != NULL) {
664 		LIST_REMOVE(rr, pentry);
665 		free(rr);
666 	}
667 	while ((rr = LIST_FIRST(&pkt->nslist)) != NULL) {
668 		LIST_REMOVE(rr, pentry);
669 		free(rr);
670 	}
671 	while ((rr = LIST_FIRST(&pkt->arlist)) != NULL) {
672 		LIST_REMOVE(rr, pentry);
673 		free(rr);
674 	}
675 }
676 
677 /* packet building */
678 void
pkt_add_question(struct pkt * pkt,struct question * qst)679 pkt_add_question(struct pkt *pkt, struct question *qst)
680 {
681 	LIST_INSERT_HEAD(&pkt->qlist, qst, entry);
682 	pkt->h.qdcount++;
683 }
684 
685 void
pkt_add_anrr(struct pkt * pkt,struct rr * rr)686 pkt_add_anrr(struct pkt *pkt, struct rr *rr)
687 {
688 	LIST_INSERT_HEAD(&pkt->anlist, rr, pentry);
689 	pkt->h.ancount++;
690 }
691 
692 void
pkt_add_nsrr(struct pkt * pkt,struct rr * rr)693 pkt_add_nsrr(struct pkt *pkt, struct rr *rr)
694 {
695 	LIST_INSERT_HEAD(&pkt->nslist, rr, pentry);
696 	pkt->h.nscount++;
697 }
698 
699 void
pkt_add_arrr(struct pkt * pkt,struct rr * rr)700 pkt_add_arrr(struct pkt *pkt, struct rr *rr)
701 {
702 	LIST_INSERT_HEAD(&pkt->arlist, rr, pentry);
703 	pkt->h.arcount++;
704 }
705 
706 int
rr_set(struct rr * rr,char dname[MAXHOSTNAMELEN],u_int16_t type,u_int16_t class,u_int32_t ttl,u_int flags,void * rdata,size_t rdlen)707 rr_set(struct rr *rr, char dname[MAXHOSTNAMELEN],
708     u_int16_t type, u_int16_t class, u_int32_t ttl,
709     u_int flags, void *rdata, size_t rdlen)
710 {
711 	bzero(rr, sizeof(*rr));
712 
713 	rr->rrs.type = type;
714 	rr->rrs.class = class;
715 	rr->ttl = ttl;
716 	rr->flags = flags;
717 	strlcpy(rr->rrs.dname, dname, sizeof(rr->rrs.dname));
718 
719 	if (rdata != NULL) {
720 		if (rdlen > sizeof(rr->rdata)) {
721 			log_debug("rr_set: Invalid rdlen %zd", rdlen);
722 			return (-1);
723 		}
724 		memcpy(&rr->rdata, rdata, rdlen);
725 	}
726 
727 	return (0);
728 }
729 
730 int
rr_rdata_cmp(struct rr * rra,struct rr * rrb)731 rr_rdata_cmp(struct rr *rra, struct rr *rrb)
732 {
733 	struct iface *iface;
734 
735 	if (rra->rrs.type != rrb->rrs.type)
736 		return (-1);
737 	if (rra->rrs.class != rrb->rrs.class)
738 		return (-1);
739 
740 	/*
741 	 * Special case, if this is a T_A record and the address is INADDR_ANY,
742 	 * we must compare agains all our interface addresses.
743 	 */
744 	if (RR_INADDRANY(rra) || RR_INADDRANY(rrb)) {
745 		LIST_FOREACH(iface, &conf->iface_list, entry) {
746 			if (iface->addr.s_addr == rra->rdata.A.s_addr)
747 				return (0);
748 			if (iface->addr.s_addr == rrb->rdata.A.s_addr)
749 				return (0);
750 		}
751 	}
752 
753 	return (memcmp(&rra->rdata, &rrb->rdata, sizeof(rra->rdata)));
754 }
755 
756 u_int32_t
rr_ttl_left(struct rr * rr)757 rr_ttl_left(struct rr *rr)
758 {
759 	struct timespec tnow;
760 	struct timespec tr;
761 
762 	if (clock_gettime(CLOCK_MONOTONIC, &tnow))
763 		fatal("clock_gettime");
764 	timespecsub(&tnow, &rr->age, &tr);
765 
766 	return (rr->ttl - (u_int32_t)tr.tv_sec);
767 }
768 
769 struct rr *
rr_dup(struct rr * rr)770 rr_dup(struct rr *rr)
771 {
772 	struct rr *rdup;
773 
774 	if ((rdup = malloc(sizeof(*rdup))) == NULL)
775 		fatal("malloc");
776 	memcpy(rdup, rr, sizeof(*rdup));
777 
778 	return (rdup);
779 }
780 
781 int
pkt_parse_header(u_int8_t ** pbuf,u_int16_t * len,struct pkt * pkt)782 pkt_parse_header(u_int8_t **pbuf, u_int16_t *len, struct pkt *pkt)
783 {
784 	u_int8_t *buf = *pbuf;
785 
786 	/* MDNS header sanity check */
787 	if (*len < HDR_LEN) {
788 		log_debug("pkt_parse_header: bad packet size %u", len);
789 		return (-1);
790 	}
791 	pkt->h = *((HEADER *) buf);
792 	header_ntohs(&pkt->h);
793 	*len  -= HDR_LEN;
794 	*pbuf += HDR_LEN;
795 
796 	return (0);
797 }
798 
799 int
pkt_parse_question(u_int8_t ** pbuf,u_int16_t * len,struct pkt * pkt)800 pkt_parse_question(u_int8_t **pbuf, u_int16_t *len, struct pkt *pkt)
801 {
802 	u_int16_t	 us;
803 	struct question *qst;
804 	ssize_t		 n;
805 
806 	/* MDNS question sanity check */
807 	if (*len < MINQRY_LEN) {
808 		log_debug("pkt_parse_question: bad query packet size %u", *len);
809 		return (-1);
810 	}
811 
812 	if ((qst = calloc(1, sizeof(*qst))) == NULL)
813 		fatal("calloc");
814 
815 	n = pkt_parse_dname(*pbuf, *len, qst->rrs.dname);
816 	if (n == -1) {
817 		free(qst);
818 		return (-1);
819 	}
820 
821 	*pbuf += n;
822 	*len  -= n;
823 
824 	GETSHORT(qst->rrs.type, *pbuf);
825 	*len -= INT16SZ;
826 
827 	GETSHORT(us, *pbuf);
828 	*len -= INT16SZ;
829 
830 	/* Deal with legacy packets */
831 	if (pkt->flags & PKT_FLAG_LEGACY) {
832 		qst->flags |= QST_FLAG_UNIRESP;
833 		qst->rrs.class = us;
834 	} else { /* Normal MDNS packets */
835 		if (us & UNIRESP_MSK)
836 			qst->flags |= QST_FLAG_UNIRESP;
837 		/* Get the class */
838 		qst->rrs.class = us & CLASS_MSK;
839 	}
840 
841 	/* This really sucks, we can't know if the class is valid prior to
842 	 * parsing the labels, I mean, we could but would be ugly */
843 	if (qst->rrs.class != C_ANY && qst->rrs.class != C_IN) {
844 		log_warnx("pkt_parse_question: Invalid packet qclass %u",
845 		    qst->rrs.class);
846 		free(qst);
847 		return (-1);
848 	}
849 
850 	LIST_INSERT_HEAD(&pkt->qlist, qst, entry);
851 
852 	return (0);
853 }
854 
855 ssize_t
pkt_parse_dname(u_int8_t * buf,u_int16_t len,char dname[MAXHOSTNAMELEN])856 pkt_parse_dname(u_int8_t *buf, u_int16_t len, char dname[MAXHOSTNAMELEN])
857 {
858 	size_t i;
859 	u_int8_t lablen;
860 	int jumped = 0;
861 	u_int16_t oldlen = len;
862 	size_t slen;
863 	char label[MAXLABELLEN];
864 
865 	/* be extra safe */
866 	bzero(dname, MAXHOSTNAMELEN);
867 
868 	for (i = 0; i < MAXLABELS; i++) {
869 		/* check if head is a pointer */
870 		if (*buf & NAMECOMP_BYTE_MSK) {
871 			u_int16_t us, ncoff;
872 
873 			GETSHORT(us, buf);
874 			if (!jumped)
875 				len -= INT16SZ;
876 			ncoff = us & NAMEADDR_MSK;
877 			/*
878 			 * Prevent the following:
879 			 * 1. Pointers should only point backward.
880 			 * 2. No pointer should point past buf.
881 			 */
882 			if (ncoff > pktcomp.len - len) {
883 				log_warnx("Invalid NC pointer");
884 				return (-1);
885 			}
886 			buf = pktcomp.start + ncoff;
887 			jumped = 1;
888 		}
889 
890 		/*
891 		 * XXX No support for multiple pointers yet.
892 		 */
893 		if (*buf & NAMECOMP_BYTE_MSK) {
894 			log_warnx("I can't cope with multiple compression"
895 			    " pointers");
896 			return (-1);
897 		}
898 
899 		lablen = *buf++;
900 
901 		if (lablen > sizeof(label) ||
902 		    buf + lablen > pktcomp.start + pktcomp.len) {
903 			log_warnx("Invalid lablen, too big");
904 			return (-1);
905 		}
906 
907 		if (!jumped)
908 			len--;
909 
910 		if (lablen == 0) {
911 			/* remove the trailling dot */
912 			slen = strlen(dname);
913 			if (slen > 0)
914 				dname[slen - 1] = '\0';
915 			break;
916 		}
917 
918 		if (lablen > (MAXHOSTNAMELEN - strlen(dname)) ||
919 		    lablen > MAXLABELLEN - 1) {
920 			log_warnx("label won't fit");
921 			return (-1);
922 		}
923 		memcpy(label, buf, lablen);
924 		label[lablen] = '\0';
925 		/* strlcat needs a proper C string in src */
926 		if (strlcat(dname, label, MAXHOSTNAMELEN) >= MAXHOSTNAMELEN)  {
927 			log_warnx("domain-name truncated");
928 			return (-1);
929 		}
930 
931 		/* should we leave the dot on the last tag ? */
932 		if (strlcat(dname, ".", MAXHOSTNAMELEN) >= MAXHOSTNAMELEN) {
933 			log_warnx("domain-name truncated");
934 			return (-1);
935 		}
936 
937 		buf += lablen;
938 		if (!jumped)
939 			len -= lablen;
940 	}
941 
942 	if (i == MAXLABELS) {
943 		log_warnx("max labels reached");
944 		return (-1);
945 	}
946 
947 	return (oldlen - len);
948 }
949 
950 
951 /*
952  * Fully parse a resource record ("RR").
953  * This adjusts "len" to be the number of bytes left in "pbuf", which is
954  * the packet buffer.
955  * (There may be multiple RR entries in a single request.)
956  * The "rr" field is filled in along the way.
957  * Returns -1 on failure, 0 on success.
958  */
959 int
pkt_parse_rr(u_int8_t ** pbuf,u_int16_t * len,struct rr * rr)960 pkt_parse_rr(u_int8_t **pbuf, u_int16_t *len, struct rr *rr)
961 {
962 	u_int16_t us, rdlen = 0, tmplen, i, code, plen, erc, pl;
963 	u_int32_t ul;
964 	size_t j;
965 	ssize_t n;
966 	u_char *buf;
967 
968 	n = pkt_parse_dname(*pbuf, *len, rr->rrs.dname);
969 	if (n == -1)
970 		return (-1);
971 	*pbuf += n;
972 	*len  -= n;
973 	/* Make sure rr packet len is ok */
974 	if (*len < 8) {
975 		log_warnx("RR packet length too long");
976 		return (-1);
977 	}
978 	GETSHORT(rr->rrs.type, *pbuf);
979 	*len -= INT16SZ;
980 
981 	/*
982 	 * The T_OPT type is handled differently from other RR types, so
983 	 * we jump to the type handler before reading in values that the
984 	 * OPT doesn't define.
985 	 * See RFC 2671 for details.
986 	 */
987 
988 	if (T_OPT == rr->rrs.type)
989 		goto handletype;
990 
991 	GETSHORT(us, *pbuf);
992 	*len -= INT16SZ;
993 	if (us & CACHEFLUSH_MSK)
994 		rr->flags |= RR_FLAG_CACHEFLUSH;
995 	rr->rrs.class  = us & CLASS_MSK;
996 	if (rr->rrs.class != C_ANY && rr->rrs.class != C_IN) {
997 		log_debug("pkt_parse_rr: %s (%s) Invalid packet class %u",
998 		    rr_type_name(rr->rrs.type), rr->rrs.dname, rr->rrs.class);
999 		return (-1);
1000 	}
1001 	GETLONG(rr->ttl, *pbuf);
1002 	*len -= INT32SZ;
1003 	GETSHORT(rdlen, *pbuf);
1004 	*len -= INT16SZ;
1005 	if (*len < rdlen) {
1006 		log_debug("Invalid rr data length, *len = %u, rdlen = %u",
1007 		    *len, rdlen);
1008 		return (-1);
1009 	}
1010 
1011 handletype:
1012 	switch (rr->rrs.type) {
1013 	case T_A:
1014 		buf = *pbuf;
1015 		if (rdlen != INT32SZ) {
1016 			log_debug("Invalid A record rdlen %u", rdlen);
1017 			return (-1);
1018 		}
1019 		GETLONG(ul, buf);
1020 		rr->rdata.A.s_addr = htonl(ul);
1021 		if (rr->rdata.A.s_addr == INADDR_ANY) {
1022 			log_warnx("Invalid T_A record with ip address 0.0.0.0");
1023 			return (-1);
1024 		}
1025 		break;
1026 	case T_HINFO:
1027 		if ((n = charstr(rr->rdata.HINFO.cpu, *pbuf, rdlen)) == -1)
1028 			return (-1);
1029 		if ((n = charstr(rr->rdata.HINFO.os, *pbuf + n,
1030 		    rdlen - n)) == -1)
1031 			return (-1);
1032 		break;
1033 	case T_CNAME:
1034 		if (rr_parse_dname(*pbuf, *len,
1035 		    rr->rdata.CNAME) == -1)
1036 			return (-1);
1037 		break;
1038 	case T_PTR:
1039 		if (rr_parse_dname(*pbuf, *len,
1040 		    rr->rdata.PTR) == -1)
1041 			return (-1);
1042 		break;
1043 	case T_TXT:
1044 		if ((n = charstr(rr->rdata.TXT, *pbuf, rdlen)) == -1)
1045 			return (-1);
1046 		break;
1047 	case T_NS:
1048 		if (rr_parse_dname(*pbuf, *len,
1049 		    rr->rdata.NS) == -1)
1050 			return (-1);
1051 		break;
1052 	case T_SRV:
1053 		buf = *pbuf;
1054 		tmplen = *len;
1055 		GETSHORT(rr->rdata.SRV.priority, buf);
1056 		tmplen -= INT16SZ;
1057 		GETSHORT(rr->rdata.SRV.weight, buf);
1058 		tmplen -= INT16SZ;
1059 		GETSHORT(rr->rdata.SRV.port, buf);
1060 		tmplen -= INT16SZ;
1061 		if (rr_parse_dname(buf, tmplen, rr->rdata.SRV.target) == -1)
1062 			return (-1);
1063 		break;
1064 	case T_AAAA:
1065 	case T_NSEC:
1066 		break;
1067 	case T_OPT:
1068 		/*
1069 		 * We need 8 bytes for the OPT RR frame.
1070 		 * See RFC 2671, 4.3.
1071 		 */
1072 		if (*len < 8) {
1073 			log_warnx("Bad T_OPT length");
1074 			return (-1);
1075 		}
1076 
1077 		/* sender's UDP payload size */
1078 		GETSHORT(pl, *pbuf);
1079 		*len -= INT16SZ;
1080 		/* extended RCODE and flags */
1081 		GETLONG(erc, *pbuf);
1082 		*len -= INT32SZ;
1083 		/* describes RDATA */
1084 		GETSHORT(us, *pbuf);
1085 		*len -= INT16SZ;
1086 		if (*len < us) {
1087 			log_warnx("Bad T_OPT RDATA length");
1088 			return (-1);
1089 		}
1090 
1091 		/* Parse RDATA sections. */
1092 
1093 		for (j = 0, i = 0; i < us; j++) {
1094 			GETSHORT(code, *pbuf);
1095 			*len -= INT16SZ;
1096 			i += INT16SZ;
1097 			GETSHORT(plen, *pbuf);
1098 			*len -= INT16SZ;
1099 			i += INT16SZ;
1100 			if (us - i < plen) {
1101 				log_warnx("Bad T_OPT RDATA "
1102 					"section %zu length", j);
1103 				return (-1);
1104 			}
1105 
1106 			if (4 == code)
1107 				log_debug("pkt_parse_rr: "
1108 					"edns0 \'owner-option\'");
1109 			else
1110 				log_warnx("Unknown T_OPT RDATA "
1111 					"section %zu code %u",
1112 					j, code);
1113 
1114 			*pbuf += plen;
1115 			*len -= plen;
1116 			i += plen;
1117 		}
1118 
1119 		rr->flags = 0;
1120 		rr->ttl = 0;
1121 		break;
1122 	default:
1123 		log_debug("Unknown record type %u", rr->rrs.type);
1124 		return (-1);
1125 		break;
1126 	}
1127 
1128 	*len  -= rdlen;
1129 	*pbuf += rdlen;
1130 
1131 	return (0);
1132 }
1133 
1134 int
pkt_handle_qst(struct pkt * pkt)1135 pkt_handle_qst(struct pkt *pkt)
1136 {
1137 	struct question		*qst, *lqst;
1138 	struct rr		*rr, *rrcopy, *rr_aux;
1139 	struct pkt		 sendpkt;
1140 	struct sockaddr_in	 dst, *pdst;
1141 	struct cache_node	*cn;
1142 	int			 probe;
1143 
1144 	/* TODO: Mdns draft 6.3 Duplicate Question Suppression */
1145 
1146 	pkt_init(&sendpkt);
1147 	sendpkt.h.qr = MDNS_RESPONSE;
1148 	sendpkt.iface = pkt->iface;
1149 	bzero(&dst, sizeof(dst));
1150 	pdst = NULL;
1151 
1152 	/* If legacy packet, we must copy id and answer as unicast dns  */
1153 	if (pkt->flags & PKT_FLAG_LEGACY) {
1154 		sendpkt.flags = pkt->flags;
1155 		sendpkt.h.id = pkt->h.id;
1156 		dst = pkt->ipsrc;
1157 		pdst = &dst;
1158 	}
1159 
1160 	while ((qst = LIST_FIRST(&pkt->qlist)) != NULL) {
1161 		/*
1162 		 * XXX: This assumes that every question came from the same
1163 		 * packet, hence, the same source. It also assumes QU questions
1164 		 * may not be mixed up with QM questions, maybe this flag should
1165 		 * be moved to pkt.
1166 		 */
1167 		if (qst->flags & QST_FLAG_UNIRESP) {
1168 			dst = pkt->ipsrc;
1169 			pdst = &dst;
1170 		}
1171 
1172 		/* Check if it's a probe */
1173 		probe = 0;
1174 		LIST_FOREACH(rr, &pkt->nslist, pentry) {
1175 			if (ANSWERS(&qst->rrs, &rr->rrs))
1176 				probe = 1;
1177 		}
1178 
1179 		/*
1180 		 * CACHE_FOREACH_DNAME instead of CACHE_FOREACH_RRS so that in
1181 		 * future we can do conflict resolving. Which needs to answer a
1182 		 * T_ANY.
1183 		 */
1184 		CACHE_FOREACH_DNAME(rr, cn, qst->rrs.dname) {
1185 			/* Look only for authority records */
1186 			if (!RR_AUTH(rr))
1187 				continue;
1188 			/* RR must answer question */
1189 			if (!ANSWERS(&qst->rrs, &rr->rrs))
1190 				continue;
1191 			/* If not a probe, skip unpublished */
1192 			if (!probe &&
1193 			    ((rr->flags & RR_FLAG_PUBLISHED) == 0))
1194 				continue;
1195 			/* Sanity check */
1196 			if (probe && pkt->flags & PKT_FLAG_LEGACY) {
1197 				log_warnx("Packet considered probe and legacy, "
1198 				    "dropping (%s)", rrs_str(&qst->rrs));
1199 				return (-1);
1200 			}
1201 			/*
1202 			 * If this is a probe and we have a conflict record
1203 			 * which isn't published yet, do a conflict tie break.
1204 			 */
1205 			if (probe && (rr->flags & RR_FLAG_PUBLISHED) == 0) {
1206 				log_warnx("Conflict tie break for %s",
1207 				    rrs_str(&rr->rrs));
1208 				; /* TODO Tie break */
1209 				return (-1);
1210 			}
1211 
1212 			/*
1213 			 * So we have an answer, see if we're listed in the
1214 			 * known answer supression list
1215 			 */
1216 			if (!probe) {
1217 				LIST_FOREACH(rr_aux, &pkt->anlist, pentry) {
1218 					if (rr_rdata_cmp(rr, rr_aux) == 0 &&
1219 					    rr_aux->ttl > (rr->ttl / 2)) {
1220 						/* Supress this answer */
1221 						goto supress;
1222 					}
1223 				}
1224 			}
1225 			/* If we got here we're commited to answering */
1226 			if (probe)
1227 				log_warnx("Simple conflict for %s",
1228 				    rrs_str(&rr->rrs));
1229 
1230 			/* Make a copy since we may modify if PKT_F_LEGACY */
1231 			rrcopy = rr_dup(rr);
1232 			/*
1233 			 * If this is a legacy question, get a copy rr, remove
1234 			 * the cacheflush bit and copy the qid from question.
1235 			 */
1236 			if (pkt->flags & PKT_FLAG_LEGACY) {
1237 				/* Include a copy of question */
1238 				if ((lqst = calloc(1, sizeof(*lqst))) == NULL)
1239 					fatal("calloc");
1240 				/* No flags, since we don't want any bits set */
1241 				lqst->flags = 0;
1242 				lqst->rrs   = qst->rrs;
1243 				pkt_add_question(&sendpkt, lqst);
1244 				rrcopy->flags &= ~RR_FLAG_CACHEFLUSH;
1245 				/* Draft says up to 10 */
1246 				rrcopy->ttl = 8;
1247 			}
1248 			/* Add to response packet */
1249 			pkt_add_anrr(&sendpkt, rrcopy);
1250 		 supress: ;
1251 		}
1252 		LIST_REMOVE(qst, entry);
1253 		free(qst);
1254 	}
1255 
1256 	/*
1257 	 * If we have answers, send it.
1258 	 */
1259 	if (sendpkt.h.ancount > 0)
1260 		if (pkt_sendto(&sendpkt, sendpkt.iface, pdst) == -1)
1261 			log_warnx("Can't send packet to"
1262 			    "%s", pkt->iface->name);
1263 
1264 	/* Cleanup our pkt since the RRs were dupped */
1265 	pkt_cleanup(&sendpkt);
1266 
1267 	return (0);
1268 }
1269 
1270 int
rr_parse_dname(u_int8_t * buf,u_int16_t len,char dname[MAXHOSTNAMELEN])1271 rr_parse_dname(u_int8_t *buf, u_int16_t len, char dname[MAXHOSTNAMELEN])
1272 {
1273 	if (pkt_parse_dname(buf, len, dname) == -1) {
1274 		log_warnx("rr_parse_dname: pkt_parse_dname error");
1275 		return (-1);
1276 	}
1277 
1278 	return (0);
1279 }
1280 
1281 ssize_t
serialize_dname(u_int8_t * buf,u_int16_t len,char dname[MAXHOSTNAMELEN],int compress)1282 serialize_dname(u_int8_t *buf, u_int16_t len, char dname[MAXHOSTNAMELEN],
1283     int compress)
1284 {
1285 	char *end;
1286 	char *dbuf = dname;
1287 	u_int8_t tlen;
1288 	u_int8_t *pbuf = buf;
1289 	struct namecomp *nc;
1290 
1291 	/* Try to compress this name */
1292 
1293 	if (compress &&
1294 	    (nc = pktcomp_lookup(dname)) != NULL) {
1295 		PUTSHORT(nc->offset, pbuf);
1296 		len -= INT16SZ;
1297 		return (pbuf - buf);
1298 	}
1299 
1300 	do {
1301 		if ((end = strchr(dbuf, '.')) == NULL) {
1302 			if ((end = strchr(dbuf, '\0')) == NULL)
1303 				fatalx("serialize_dname: bad dname");
1304 		}
1305 
1306 		tlen  = end - dbuf;
1307 		*pbuf++ = tlen;
1308 		if (tlen > len)
1309 			return (-1);
1310 		memcpy(pbuf, dbuf, tlen);
1311 		len  -= tlen;
1312 		pbuf += tlen;
1313 		dbuf  = end + 1;
1314 	} while (*end != '\0');
1315 
1316 	if (len == 0)
1317 		return (-1);
1318 	*pbuf++ = '\0';		/* null terminate dname */
1319 	len--;
1320 
1321 	/*
1322 	 * Add dname to name compression, buf - pktcomp->start, should give us
1323 	 * the correct offset in the current packet.
1324 	 */
1325 	if (compress)
1326 		if (pktcomp_add(dname, (u_int16_t) (buf - pktcomp.start))
1327 		    == -1)
1328 			log_warnx("pktcomp_add error: %s", dname);
1329 
1330 	return (pbuf - buf);
1331 }
1332 
1333 ssize_t
serialize_rdata(struct rr * rr,u_int8_t * buf,u_int16_t len)1334 serialize_rdata(struct rr *rr, u_int8_t *buf, u_int16_t len)
1335 {
1336 	u_int8_t	*prdlen, *pbuf = buf;
1337 	ssize_t		 n;
1338 	u_int16_t	 rdlen = 0;
1339 	u_int8_t	 cpulen, oslen;
1340 
1341 	switch (rr->rrs.type) {
1342 	case T_HINFO:
1343 		cpulen = strlen(rr->rdata.HINFO.cpu);
1344 		oslen = strlen(rr->rdata.HINFO.os);
1345 		rdlen = cpulen + oslen + 2;	/* 2 length octets */
1346 		if (len < rdlen)
1347 			return (-1);
1348 		PUTSHORT(rdlen, pbuf);
1349 		len -= 2;
1350 		/* fill cpu */
1351 		*pbuf++ = cpulen;
1352 		len--;
1353 		memcpy(pbuf, rr->rdata.HINFO.cpu, cpulen);
1354 		pbuf += cpulen;
1355 		len  -= cpulen;
1356 		/* fill os */
1357 		*pbuf++ = oslen;
1358 		len--;
1359 		memcpy(pbuf, rr->rdata.HINFO.os, oslen);
1360 		pbuf += oslen;
1361 		len  -= oslen;
1362 		break;
1363 	case T_PTR:
1364 	case T_TXT:
1365 		prdlen = pbuf;
1366 		/* jump over rdlen */
1367 		pbuf += INT16SZ;
1368 		len  -= INT16SZ;
1369 		/* NOTE rr->rdata.PTR == rr->rdata.TXT */
1370 		if ((n = serialize_dname(pbuf, len,
1371 		    rr->rdata.PTR, 1)) == -1)
1372 			return (-1);
1373 		rdlen = n;
1374 		pbuf += rdlen;
1375 		len  -= rdlen;
1376 		PUTSHORT(rdlen, prdlen);
1377 		break;
1378 	case T_A:
1379 		rdlen = INT32SZ;
1380 		if (len < (rdlen + INT16SZ)) /* INT16SZ is rdlen itself */
1381 			return (-1);
1382 		PUTSHORT(rdlen, pbuf);
1383 		len -= 2;
1384 		memcpy(pbuf, &rr->rdata, rdlen);
1385 		pbuf += rdlen;
1386 		len  -= rdlen;
1387 		break;
1388 	case T_SRV:
1389 		prdlen = pbuf;
1390 		/* jump over rdlen */
1391 		if (len < INT16SZ)
1392 			return (-1);
1393 		pbuf += INT16SZ;
1394 		len  -= INT16SZ;
1395 		if (len < INT16SZ * 3)
1396 			return (-1);
1397 		PUTSHORT(rr->rdata.SRV.priority, pbuf);
1398 		len   -= INT16SZ;
1399 		rdlen += INT16SZ;
1400 		PUTSHORT(rr->rdata.SRV.weight, pbuf);
1401 		len   -= INT16SZ;
1402 		rdlen += INT16SZ;
1403 		PUTSHORT(rr->rdata.SRV.port, pbuf);
1404 		len   -= INT16SZ;
1405 		rdlen += INT16SZ;
1406 		if ((n = serialize_dname(pbuf, len,
1407 		    rr->rdata.SRV.target, 0)) == -1)
1408 			return (-1);
1409 		rdlen += n;
1410 		pbuf  += n;
1411 		len   -= n;
1412 		PUTSHORT(rdlen, prdlen);
1413 		break;
1414 	default:
1415 		log_warnx("serialize_rdata: Don't know how to serialize %s (%d)",
1416 		    rr_type_name(rr->rrs.type), rr->rrs.type);
1417 		return (-1);
1418 		break;		/* NOTREACHED */
1419 	}
1420 	return (pbuf - buf);
1421 }
1422 
1423 ssize_t
serialize_rr(struct rr * rr,u_int8_t * buf,u_int16_t len)1424 serialize_rr(struct rr *rr, u_int8_t *buf, u_int16_t len)
1425 {
1426 	u_int8_t	*pbuf = buf;
1427 	u_int16_t	 us   = 0;
1428 	ssize_t		 n;
1429 
1430 	n = serialize_dname(pbuf, len, rr->rrs.dname, 1);
1431 	if (n == -1 || n > len)
1432 		return (-1);
1433 	pbuf += n;
1434 	len  -= n;
1435 	if (len == 0)
1436 		return (-1);
1437 
1438 	if (len < 8) /* must fit type, class, ttl */
1439 		return (-1);
1440 	PUTSHORT(rr->rrs.type, pbuf);
1441 	us = rr->rrs.class;
1442 	if (rr->flags & RR_FLAG_CACHEFLUSH)
1443 		us |= CACHEFLUSH_MSK;
1444 	PUTSHORT(us, pbuf);
1445 	PUTLONG(rr->ttl, pbuf);
1446 	len -= 8;
1447 
1448 	n = serialize_rdata(rr, pbuf, len);
1449 	if (n == -1 || n > len)
1450 		return (-1);
1451 	pbuf += n;
1452 	len  -= n;
1453 
1454 	return (pbuf - buf);
1455 }
1456 
1457 ssize_t
serialize_qst(struct question * qst,u_int8_t * buf,u_int16_t len)1458 serialize_qst(struct question *qst, u_int8_t *buf, u_int16_t len)
1459 {
1460 	u_int8_t *pbuf = buf;
1461 	u_int16_t qclass;
1462 	ssize_t n;
1463 
1464 	n = serialize_dname(pbuf, len, qst->rrs.dname, 1);
1465 	if (n == -1 || n > len)
1466 		return (-1);
1467 	pbuf += n;
1468 	len  -= n;
1469 	if (len == 0)
1470 		return (-1);
1471 
1472 	if (len < 4)	/* must fit type, class */
1473 		return (-1);
1474 	PUTSHORT(qst->rrs.type, pbuf);
1475 
1476 	qclass = qst->rrs.class;
1477 	if (qst->flags & QST_FLAG_UNIRESP)
1478 		qclass = qst->rrs.class | UNIRESP_MSK;
1479 	PUTSHORT(qclass, pbuf);
1480 
1481 	return (pbuf - buf);
1482 }
1483 
1484 void
header_htons(HEADER * h)1485 header_htons(HEADER *h)
1486 {
1487 	h->qdcount = htons(h->qdcount);
1488 	h->ancount = htons(h->ancount);
1489 	h->nscount = htons(h->nscount);
1490 	h->arcount = htons(h->arcount);
1491 }
1492 
1493 void
header_ntohs(HEADER * h)1494 header_ntohs(HEADER *h)
1495 {
1496 	h->qdcount = ntohs(h->qdcount);
1497 	h->ancount = ntohs(h->ancount);
1498 	h->nscount = ntohs(h->nscount);
1499 	h->arcount = ntohs(h->arcount);
1500 }
1501 
1502 /* Packet compression */
1503 void
pktcomp_reset(int first,u_int8_t * start,u_int16_t len)1504 pktcomp_reset(int first, u_int8_t *start, u_int16_t len)
1505 {
1506 	struct namecomp *nc;
1507 
1508 	while ((nc = LIST_FIRST(&pktcomp.namecomp_list)) != NULL) {
1509 		LIST_REMOVE(nc, entry);
1510 		free(nc);
1511 	}
1512 	pktcomp.start = start;
1513 	pktcomp.len = len;
1514 }
1515 
1516 int
pktcomp_add(char dname[MAXHOSTNAMELEN],u_int16_t offset)1517 pktcomp_add(char dname[MAXHOSTNAMELEN], u_int16_t offset)
1518 {
1519 	struct namecomp *nc;
1520 
1521 	if ((nc = calloc(1, sizeof(*nc))) == NULL)
1522 		fatal("calloc");
1523 	strlcpy(nc->dname, dname, sizeof(nc->dname));
1524 	nc->offset = offset | NAMECOMP_MSK;
1525 	LIST_INSERT_HEAD(&pktcomp.namecomp_list, nc, entry);
1526 
1527 	return (0);
1528 }
1529 
1530 struct namecomp *
pktcomp_lookup(char dname[MAXHOSTNAMELEN])1531 pktcomp_lookup(char dname[MAXHOSTNAMELEN])
1532 {
1533 	struct namecomp *nc;
1534 
1535 	LIST_FOREACH(nc, &pktcomp.namecomp_list, entry) {
1536 		if (strcmp(nc->dname, dname) == 0)
1537 			return (nc);
1538 	}
1539 
1540 	return (NULL);
1541 }
1542 
1543 /* Util */
1544 ssize_t
charstr(char dest[MAXCHARSTR],u_int8_t * buf,u_int16_t len)1545 charstr(char dest[MAXCHARSTR], u_int8_t *buf, u_int16_t len)
1546 {
1547 	u_int8_t tocpy;
1548 
1549 	tocpy = *buf++;
1550 
1551 	if (tocpy > len) {
1552 		log_debug("tocpy: %u > len: %u", tocpy, len);
1553 		return (-1);
1554 	}
1555 
1556 	/* This isn't a case for strlcpy */
1557 	memcpy(dest, buf, tocpy);
1558 	dest[tocpy] = '\0';	/* Assure null terminated */
1559 
1560 	return (tocpy + 1);
1561 }
1562