1 /*
2  * ldns-testns. Light-weight DNS daemon, gives canned replies.
3  *
4  * Tiny dns server, that responds with specially crafted replies
5  * to requests. For testing dns software.
6  *
7  * (c) NLnet Labs, 2005 - 2008
8  * See the file LICENSE for the license
9  */
10 
11 /*
12  * This program is a debugging aid. It can is not efficient, especially
13  * with a long config file, but it can give any reply to any query.
14  * This can help the developer pre-script replies for queries.
15  *
16  * It listens to IP4 UDP and TCP by default.
17  * You can specify a packet RR by RR with header flags to return.
18  *
19  * Missing features:
20  *		- matching content different from reply content.
21  *		- find way to adjust mangled packets?
22  */
23 
24 /*
25 	The data file format is as follows:
26 
27 	; comment.
28 	; a number of entries, these are processed first to last.
29 	; a line based format.
30 
31 	$ORIGIN origin
32 	$TTL default_ttl
33 
34 	ENTRY_BEGIN
35 	; first give MATCH lines, that say what queries are matched
36 	; by this entry.
37 	; 'opcode' makes the query match the opcode from the reply
38 	; if you leave it out, any opcode matches this entry.
39 	; 'qtype' makes the query match the qtype from the reply
40 	; 'qname' makes the query match the qname from the reply
41 	; 'serial=1023' makes the query match if ixfr serial is 1023.
42 	MATCH [opcode] [qtype] [qname] [serial=<value>]
43 	MATCH [UDP|TCP]
44 	MATCH ...
45 	; Then the REPLY header is specified.
46 	REPLY opcode, rcode or flags.
47 		(opcode)  QUERY IQUERY STATUS NOTIFY UPDATE
48 		(rcode)   NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN
49 		 		YXRRSET NXRRSET NOTAUTH NOTZONE
50 		(flags)   QR AA TC RD CD RA AD
51 	REPLY ...
52 	; any additional actions to do.
53 	; 'copy_id' copies the ID from the query to the answer.
54 	ADJUST copy_id
55 	; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
56 	ADJUST [sleep=<num>]    ; sleep before giving any reply
57 	ADJUST [packet_sleep=<num>]  ; sleep before this packet in sequence
58 	SECTION QUESTION
59 	<RRs, one per line>    ; the RRcount is determined automatically.
60 	SECTION ANSWER
61 	<RRs, one per line>
62 	SECTION AUTHORITY
63 	<RRs, one per line>
64 	SECTION ADDITIONAL
65 	<RRs, one per line>
66 	EXTRA_PACKET		; follow with SECTION, REPLY for more packets.
67 	HEX_ANSWER_BEGIN	; follow with hex data
68 				; this replaces any answer packet constructed
69 				; with the SECTION keywords (only SECTION QUERY
70 				; is used to match queries). If the data cannot
71 				; be parsed, ADJUST rules for the answer packet
72 				; are ignored
73 	HEX_ANSWER_END
74 	ENTRY_END
75 */
76 
77 /* Example data file:
78 $ORIGIN nlnetlabs.nl
79 $TTL 3600
80 
81 ENTRY_BEGIN
82 MATCH qname
83 REPLY NOERROR
84 ADJUST copy_id
85 SECTION QUESTION
86 www.nlnetlabs.nl.	IN	A
87 SECTION ANSWER
88 www.nlnetlabs.nl.	IN	A	195.169.215.155
89 SECTION AUTHORITY
90 nlnetlabs.nl.		IN	NS	www.nlnetlabs.nl.
91 ENTRY_END
92 
93 ENTRY_BEGIN
94 MATCH qname
95 REPLY NOERROR
96 ADJUST copy_id
97 SECTION QUESTION
98 www2.nlnetlabs.nl.	IN	A
99 HEX_ANSWER_BEGIN
100 ; 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
101 ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
102  00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e	;	   1-  20
103  61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77	;	  21-  40
104  77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01	;	  41-  60
105  00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65	;	  61-  80
106  70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03	;	  81- 100
107  6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e	;	 101- 120
108  61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50	;	 121- 140
109  8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00	;	 141- 160
110  03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00	;	 161- 180
111  01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f	;	 181- 200
112  6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc	;	 201- 220
113  db 5b
114 HEX_ANSWER_END
115 ENTRY_END
116 
117 
118 */
119 
120 struct sockaddr_storage;
121 #include "config.h"
122 #include <ldns/ldns.h>
123 #include "ldns-testpkts.h"
124 
125 #ifdef HAVE_SYS_SOCKET_H
126 #include <sys/socket.h>
127 #endif
128 #ifdef HAVE_TIME_H
129 #include <time.h>
130 #endif
131 #ifdef HAVE_SYS_TIME_H
132 #include <sys/time.h>
133 #endif
134 #ifdef HAVE_SYS_SELECT_H
135 #include <sys/select.h>
136 #endif
137 #ifdef HAVE_ARPA_INET_H
138 #include <arpa/inet.h>
139 #endif
140 #ifdef HAVE_NETINET_IN_H
141 #include <netinet/in.h>
142 #endif
143 #ifdef HAVE_NETINET_UDP_H
144 #include <netinet/udp.h>
145 #endif
146 #ifdef HAVE_NETINET_IGMP_H
147 #include <netinet/igmp.h>
148 #endif
149 #include <errno.h>
150 #include <signal.h>
151 
152 #ifdef HAVE_TARGETCONDITIONALS_H
153 #include <TargetConditionals.h>
154 #endif
155 
156 #if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
157 #undef HAVE_FORK
158 #endif
159 
160 #define INBUF_SIZE 4096         /* max size for incoming queries */
161 #define DEFAULT_PORT 53		/* default if no -p port is specified */
162 #define CONN_BACKLOG 256	/* connections queued up for tcp */
163 static const char* prog_name = "ldns-testns";
164 static FILE* logfile = 0;
165 static int do_verbose = 0;
166 
usage(void)167 static void usage(void)
168 {
169 	printf("Usage: %s [options] <datafile>\n", prog_name);
170 	printf("  -r	listens on random port. Port number is printed.\n");
171 	printf("  -p	listens on the specified port, default %d.\n", DEFAULT_PORT);
172 	printf("  -f	forks given number extra instances, default none.\n");
173 	printf("  -v	more verbose, prints queries, answers and matching.\n");
174 	printf("  -6	listen on IP6 any address, instead of IP4 any address.\n");
175 	printf("The program answers queries with canned replies from the datafile.\n");
176 	exit(EXIT_FAILURE);
177 }
178 
log_msg(const char * msg,...)179 static void log_msg(const char* msg, ...)
180 {
181 	va_list args;
182 	va_start(args, msg);
183 	vfprintf(logfile, msg, args);
184 	fflush(logfile);
185 	va_end(args);
186 }
187 
error(const char * msg,...)188 static void error(const char* msg, ...)
189 {
190 	va_list args;
191 	va_start(args, msg);
192 	fprintf(logfile, "%s error: ", prog_name);
193 	vfprintf(logfile, msg, args);
194 	fprintf(logfile, "\n");
195 	fflush(logfile);
196 	va_end(args);
197 	exit(EXIT_FAILURE);
198 }
199 
200 void verbose(int lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3);
verbose(int ATTR_UNUSED (lvl),const char * msg,...)201 void verbose(int ATTR_UNUSED(lvl), const char* msg, ...)
202 {
203 	va_list args;
204 	va_start(args, msg);
205 	if(do_verbose)
206 		vfprintf(logfile, msg, args);
207 	fflush(logfile);
208 	va_end(args);
209 }
210 
bind_port(int sock,int port,int fam)211 static int bind_port(int sock, int port, int fam)
212 {
213     struct sockaddr_in addr;
214 #if defined(AF_INET6) && defined(HAVE_GETADDRINFO)
215     if(fam == AF_INET6) {
216     	struct sockaddr_in6 addr6;
217 	memset(&addr6, 0, sizeof(addr6));
218 	addr6.sin6_family = AF_INET6;
219     	addr6.sin6_port = (in_port_t)htons((uint16_t)port);
220 #  if HAVE_DECL_IN6ADDR_ANY
221 	addr6.sin6_addr = in6addr_any;
222 #  else
223 	memset(&addr6.sin6_addr, 0, sizeof(addr6.sin6_addr));
224 #  endif
225     	return bind(sock, (struct sockaddr *)&addr6, (socklen_t) sizeof(addr6));
226     }
227 #endif
228 
229 #ifndef S_SPLINT_S
230     addr.sin_family = AF_INET;
231 #endif
232     addr.sin_port = (in_port_t)htons((uint16_t)port);
233     addr.sin_addr.s_addr = INADDR_ANY;
234     return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
235 }
236 
237 struct handle_udp_userdata {
238 	int udp_sock;
239 	struct sockaddr_storage addr_him;
240 	socklen_t hislen;
241 };
242 static void
send_udp(uint8_t * buf,size_t len,void * data)243 send_udp(uint8_t* buf, size_t len, void* data)
244 {
245 	struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data;
246 	/* udp send reply */
247 	ssize_t nb;
248 	nb = sendto(userdata->udp_sock, (void*)buf, len, 0,
249 		(struct sockaddr*)&userdata->addr_him, userdata->hislen);
250 	if(nb == -1)
251 		log_msg("sendto(): %s\n", strerror(errno));
252 	else if((size_t)nb != len)
253 		log_msg("sendto(): only sent %d of %d octets.\n",
254 			(int)nb, (int)len);
255 }
256 
257 static void
handle_udp(int udp_sock,struct entry * entries,int * count)258 handle_udp(int udp_sock, struct entry* entries, int *count)
259 {
260 	ssize_t nb;
261 	uint8_t inbuf[INBUF_SIZE];
262 	struct handle_udp_userdata userdata;
263 	userdata.udp_sock = udp_sock;
264 
265 	userdata.hislen = (socklen_t)sizeof(userdata.addr_him);
266 	/* udp recv */
267 	nb = recvfrom(udp_sock, (void*)inbuf, INBUF_SIZE, 0,
268 		(struct sockaddr*)&userdata.addr_him, &userdata.hislen);
269 	if (nb < 1) {
270 #ifndef USE_WINSOCK
271 		log_msg("recvfrom(): %s\n", strerror(errno));
272 #else
273 		if(WSAGetLastError() != WSAEINPROGRESS &&
274 			WSAGetLastError() != WSAECONNRESET &&
275 			WSAGetLastError()!= WSAEWOULDBLOCK)
276 			log_msg("recvfrom(): %d\n", WSAGetLastError());
277 #endif
278 		return;
279 	}
280 	handle_query(inbuf, nb, entries, count, transport_udp, send_udp,
281 		&userdata, do_verbose?logfile:0);
282 }
283 
284 static int
read_n_bytes(int sock,uint8_t * buf,size_t sz)285 read_n_bytes(int sock, uint8_t* buf, size_t sz)
286 {
287 	size_t count = 0;
288 	while(count < sz) {
289 		ssize_t nb = recv(sock, (void*)(buf+count), sz-count, 0);
290 		if(nb < 0) {
291 			log_msg("recv(): %s\n", strerror(errno));
292 			return -1;
293 		} else if(nb == 0) {
294 			log_msg("recv: remote end closed the channel\n");
295 			return sz-count;
296 		}
297 		count += nb;
298 	}
299 	return 0;
300 }
301 
302 static void
write_n_bytes(int sock,uint8_t * buf,size_t sz)303 write_n_bytes(int sock, uint8_t* buf, size_t sz)
304 {
305 	size_t count = 0;
306 	while(count < sz) {
307 		ssize_t nb = send(sock, (void*)(buf+count), sz-count, 0);
308 		if(nb < 0) {
309 			log_msg("send(): %s\n", strerror(errno));
310 			return;
311 		}
312 		count += nb;
313 	}
314 }
315 
316 struct handle_tcp_userdata {
317 	int s;
318 };
319 static void
send_tcp(uint8_t * buf,size_t len,void * data)320 send_tcp(uint8_t* buf, size_t len, void* data)
321 {
322 	struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data;
323 	uint16_t tcplen;
324 	/* tcp send reply */
325 	tcplen = htons(len);
326 	write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen));
327 	write_n_bytes(userdata->s, buf, len);
328 }
329 
330 static void
handle_tcp(int tcp_sock,struct entry * entries,int * count)331 handle_tcp(int tcp_sock, struct entry* entries, int *count)
332 {
333 	int s;
334 	struct sockaddr_storage addr_him;
335 	socklen_t hislen;
336 	uint8_t inbuf[INBUF_SIZE];
337 	uint16_t tcplen = 0;
338 	struct handle_tcp_userdata userdata;
339 
340 	/* accept */
341 	hislen = (socklen_t)sizeof(addr_him);
342 	if((s = accept(tcp_sock, (struct sockaddr*)&addr_him, &hislen)) < 0) {
343 		log_msg("accept(): %s\n", strerror(errno));
344 		return;
345 	}
346 	userdata.s = s;
347 
348 	while(1) {
349 		/* tcp recv */
350 		if (read_n_bytes(s, (uint8_t*)&tcplen, sizeof(tcplen))) {
351 #ifndef USE_WINSOCK
352 			close(s);
353 #else
354 			closesocket(s);
355 #endif
356 			return;
357 		}
358 		tcplen = ntohs(tcplen);
359 		if(tcplen >= INBUF_SIZE) {
360 			log_msg("query %d bytes too large, buffer %d bytes.\n",
361 				tcplen, INBUF_SIZE);
362 #ifndef USE_WINSOCK
363 			close(s);
364 #else
365 			closesocket(s);
366 #endif
367 			return;
368 		}
369 		if (read_n_bytes(s, inbuf, tcplen)) {
370 #ifndef USE_WINSOCK
371 			close(s);
372 #else
373 			closesocket(s);
374 #endif
375 			return;
376 		}
377 
378 		handle_query(inbuf, (ssize_t) tcplen, entries, count, transport_tcp,
379 			send_tcp, &userdata, do_verbose?logfile:0);
380 
381 		/* another query straight away? */
382 		if(1) {
383 			fd_set rset;
384 			struct timeval tv;
385 			int ret;
386 			FD_ZERO(&rset);
387 			FD_SET(s, &rset);
388 			tv.tv_sec = 0;
389 			tv.tv_usec = 100*1000;
390 			ret = select(s+1, &rset, NULL, NULL, &tv);
391 			if(ret < 0) {
392 				error("select(): %s\n", strerror(errno));
393 			}
394 			if(ret == 0) {
395 				/* timeout */
396 				break;
397 			}
398 		}
399 	}
400 #ifndef USE_WINSOCK
401 	close(s);
402 #else
403 	closesocket(s);
404 #endif
405 
406 }
407 
408 /** shared by the service and main routine (forked and threaded) */
409 static int udp_sock, tcp_sock;
410 static struct entry* entries;
411 
412 /**
413  * Test DNS server service, uses global udpsock, tcpsock, reply entries
414  * The signature is kept void so the function can be used as a thread function.
415  */
416 static void
service(void)417 service(void)
418 {
419 	fd_set rset, wset, eset;
420 	int count;
421 	int maxfd;
422 
423 	/* service */
424 	count = 0;
425 	while (1) {
426 #ifndef S_SPLINT_S
427 		FD_ZERO(&rset);
428 		FD_ZERO(&wset);
429 		FD_ZERO(&eset);
430 		FD_SET(udp_sock, &rset);
431 		FD_SET(tcp_sock, &rset);
432 #endif
433 		maxfd = udp_sock;
434 		if(tcp_sock > maxfd)
435 			maxfd = tcp_sock;
436 		if(select(maxfd+1, &rset, &wset, &eset, NULL) < 0) {
437 			error("select(): %s\n", strerror(errno));
438 		}
439 		if(FD_ISSET(udp_sock, &rset)) {
440 			handle_udp(udp_sock, entries, &count);
441 		}
442 		if(FD_ISSET(tcp_sock, &rset)) {
443 			handle_tcp(tcp_sock, entries, &count);
444 		}
445 	}
446 }
447 
448 static void
forkit(int number)449 forkit(int number)
450 {
451 	int i;
452 	for(i=0; i<number; i++)
453 	{
454 #if !defined(HAVE_FORK) || !defined(HAVE_FORK_AVAILABLE)
455 #ifndef USE_WINSOCK
456 		log_msg("fork() not available.\n");
457 		exit(1);
458 #else /* USE_WINSOCK */
459 		DWORD tid;
460 		HANDLE id = CreateThread(NULL, 0,
461 			(LPTHREAD_START_ROUTINE)service, NULL,
462 			0, &tid);
463 		if(id == NULL) {
464 			log_msg("error CreateThread: %d\n", GetLastError());
465 			return;
466 		}
467 		log_msg("thread id: %d\n", (int)tid);
468 #endif /* USE_WINSOCK */
469 #else /* HAVE_FORK */
470 		pid_t pid = fork();
471 		if(pid == (pid_t) -1) {
472 			log_msg("error forking: %s\n", strerror(errno));
473 			return;
474 		}
475 		if(pid == 0)
476 			return; /* child starts serving */
477 		log_msg("forked pid: %d\n", (int)pid);
478 #endif /* HAVE_FORK */
479 	}
480 }
481 
482 int
main(int argc,char ** argv)483 main(int argc, char **argv)
484 {
485 	/* arguments */
486 	int c;
487 	int port = DEFAULT_PORT;
488 	const char* datafile;
489 	int forknum = 0;
490 
491 	/* network */
492 	int fam = AF_INET;
493 	bool random_port_success;
494 
495 #ifdef USE_WINSOCK
496 	WSADATA wsa_data;
497 #endif
498 
499 	/* parse arguments */
500 	srandom(time(NULL) ^ getpid());
501 	logfile = stdout;
502 	prog_name = argv[0];
503 	log_msg("%s: start\n", prog_name);
504 	while((c = getopt(argc, argv, "6f:p:rv")) != -1) {
505 		switch(c) {
506 		case '6':
507 #ifdef AF_INET6
508 			fam = AF_INET6;
509 #else
510 			log_msg("cannot -6: no IP6 available\n");
511 			exit(1);
512 #endif
513 			break;
514 		case 'r':
515                 	port = 0;
516                 	break;
517 		case 'f':
518                 	forknum = atoi(optarg);
519 			if(forknum < 1)
520 				error("invalid forkno %s, give number", optarg);
521                 	break;
522 		case 'p':
523 			port = atoi(optarg);
524 			if (port < 1) {
525 				error("Invalid port %s, use a number.", optarg);
526 			}
527 			break;
528 		case 'v':
529 			do_verbose++;
530 			break;
531 		default:
532 			usage();
533 			break;
534 		}
535 	}
536 	argc -= optind;
537 	argv += optind;
538 
539 	if(argc == 0 || argc > 1)
540 		usage();
541 
542 	datafile = argv[0];
543 	log_msg("Reading datafile %s\n", datafile);
544 	entries = read_datafile(datafile, 0);
545 
546 #ifdef SIGPIPE
547         (void)signal(SIGPIPE, SIG_IGN);
548 #endif
549 #ifdef USE_WINSOCK
550 	if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0)
551 		error("WSAStartup failed\n");
552 #endif
553 
554 	if((udp_sock = socket(fam, SOCK_DGRAM, 0)) < 0) {
555 		error("udp socket(): %s\n", strerror(errno));
556 	}
557 	if((tcp_sock = socket(fam, SOCK_STREAM, 0)) < 0) {
558 		error("tcp socket(): %s\n", strerror(errno));
559 	}
560 	c = 1;
561 	if(setsockopt(tcp_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&c, (socklen_t) sizeof(int)) < 0) {
562 		error("setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
563 	}
564 
565 	/* bind ip4 */
566 	if (port > 0) {
567 		if (bind_port(udp_sock, port, fam)) {
568 			error("cannot bind(): %s\n", strerror(errno));
569 		}
570 		if (bind_port(tcp_sock, port, fam)) {
571 			error("cannot bind(): %s\n", strerror(errno));
572 		}
573 		if (listen(tcp_sock, CONN_BACKLOG) < 0) {
574 			error("listen(): %s\n", strerror(errno));
575 		}
576 	} else {
577 		random_port_success = false;
578 		while (!random_port_success) {
579 			port = (random() % 64510) + 1025;
580 			log_msg("trying to bind to port %d\n", port);
581 			random_port_success = true;
582 			if (bind_port(udp_sock, port, fam)) {
583 #ifdef EADDRINUSE
584 				if (errno != EADDRINUSE) {
585 #elif defined(USE_WINSOCK)
586 				if (WSAGetLastError() != WSAEADDRINUSE) {
587 #else
588 				if (1) {
589 #endif
590 					perror("bind()");
591 					return -1;
592 				} else {
593 					random_port_success = false;
594 				}
595 			}
596 			if (random_port_success) {
597 				if (bind_port(tcp_sock, port, fam)) {
598 #ifdef EADDRINUSE
599 					if (errno != EADDRINUSE) {
600 #elif defined(USE_WINSOCK)
601 					if (WSAGetLastError()!=WSAEADDRINUSE){
602 #else
603 					if (1) {
604 #endif
605 						perror("bind()");
606 						return -1;
607 					} else {
608 						random_port_success = false;
609 					}
610 				}
611 			}
612 			if (random_port_success) {
613 				if (listen(tcp_sock, CONN_BACKLOG) < 0) {
614 					error("listen(): %s\n", strerror(errno));
615 				}
616 			}
617 
618 		}
619 	}
620 	log_msg("Listening on port %d\n", port);
621 
622 	/* forky! */
623 	if(forknum > 0)
624 		forkit(forknum);
625 
626 	service();
627 
628         return 0;
629 }
630