Home | History | Annotate | Line # | Download | only in named
fuzz.c revision 1.2.2.2
      1 /*	$NetBSD: fuzz.c,v 1.2.2.2 2018/09/06 06:53:56 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 #include "config.h"
     15 
     16 #include <named/fuzz.h>
     17 
     18 #ifdef ENABLE_AFL
     19 #include <named/globals.h>
     20 #include <named/server.h>
     21 #include <sys/errno.h>
     22 
     23 #include <isc/app.h>
     24 #include <isc/condition.h>
     25 #include <isc/mutex.h>
     26 #include <isc/thread.h>
     27 #include <isc/util.h>
     28 #include <named/log.h>
     29 #include <dns/log.h>
     30 
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <signal.h>
     34 #include <arpa/inet.h>
     35 #include <unistd.h>
     36 #include <pthread.h>
     37 
     38 #ifndef __AFL_LOOP
     39 #error To use American Fuzzy Lop you have to set CC to afl-clang-fast!!!
     40 #endif
     41 
     42 /*
     43  * We are using pthreads directly because we might be using it with
     44  * unthreaded version of BIND, where all thread functions are
     45  * mocks. Since AFL for now only works on Linux it's not a problem.
     46  */
     47 static pthread_cond_t cond;
     48 static pthread_mutex_t mutex;
     49 static isc_boolean_t ready;
     50 
     51 /*
     52  * In "client:" mode, this thread reads fuzzed query messages from AFL
     53  * from standard input and sends it to named's listening port (DNS) that
     54  * is passed in the -A client:<address>:<port> option. It can be used to
     55  * test named from the client side.
     56  */
     57 static void *
     58 fuzz_thread_client(void *arg) {
     59 	char *host;
     60 	char *port;
     61 	struct sockaddr_in servaddr;
     62 	int sockfd;
     63 	int loop;
     64 	void *buf;
     65 
     66 	UNUSED(arg);
     67 
     68 	/*
     69 	 * Parse named -A argument in the "address:port" syntax. Due to
     70 	 * the syntax used, this only supports IPv4 addresses.
     71 	 */
     72 	host = strdup(named_g_fuzz_addr);
     73 	RUNTIME_CHECK(host != NULL);
     74 
     75 	port = strchr(host, ':');
     76 	RUNTIME_CHECK(port != NULL);
     77 	*port = 0;
     78 	++port;
     79 
     80 	memset(&servaddr, 0, sizeof (servaddr));
     81 	servaddr.sin_family = AF_INET;
     82 	RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
     83 	servaddr.sin_port = htons(atoi(port));
     84 
     85 	free(host);
     86 
     87 	/*
     88 	 * Wait for named to start. This is set in run_server() in the
     89 	 * named thread.
     90 	 */
     91 	while (!named_g_run_done) {
     92 		usleep(10000);
     93 	}
     94 
     95 	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     96 	RUNTIME_CHECK(sockfd != -1);
     97 
     98 	buf = malloc(65536);
     99 	RUNTIME_CHECK(buf != NULL);
    100 
    101 	/*
    102 	 * Processing fuzzed packets 100,000 times before shutting down
    103 	 * the app.
    104 	 */
    105 	for (loop = 0; loop < 100000; loop++) {
    106 		ssize_t length;
    107 		ssize_t sent;
    108 
    109 		length = read(0, buf, 65536);
    110 		if (length <= 0) {
    111 			usleep(1000000);
    112 			continue;
    113 		}
    114 
    115 		/*
    116 		 * Ignore packets that are larger than 4096 bytes.
    117 		 */
    118 		if (length > 4096) {
    119 			/*
    120 			 * AFL_CMIN doesn't support persistent mode, so
    121 			 * shutdown the server.
    122 			 */
    123 			if (getenv("AFL_CMIN")) {
    124 				free(buf);
    125 				close(sockfd);
    126 				named_server_flushonshutdown(named_g_server,
    127 							     ISC_FALSE);
    128 				isc_app_shutdown();
    129 				return (NULL);
    130 			}
    131 			raise(SIGSTOP);
    132 			continue;
    133 		}
    134 
    135 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    136 
    137 		ready = ISC_FALSE;
    138 
    139 		sent = sendto(sockfd, buf, length, 0,
    140 			      (struct sockaddr *) &servaddr, sizeof(servaddr));
    141 		RUNTIME_CHECK(sent == length);
    142 
    143 		/*
    144 		 * Read the reply message from named to unclog it. Don't
    145 		 * bother if there isn't a reply.
    146 		 */
    147 		recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL);
    148 
    149 		while (!ready)
    150 			pthread_cond_wait(&cond, &mutex);
    151 
    152 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    153 	}
    154 
    155 	free(buf);
    156 	close(sockfd);
    157 
    158 	named_server_flushonshutdown(named_g_server, ISC_FALSE);
    159 	isc_app_shutdown();
    160 
    161 	return (NULL);
    162 }
    163 
    164 /*
    165  * In "resolver:" mode, this thread reads fuzzed reply messages from AFL
    166  * from standard input. It also sets up a listener as a remote
    167  * authoritative server and sends a driver query to the client side of
    168  * named(resolver).  When named(resolver) connects to this authoritative
    169  * server, this thread writes the fuzzed reply message from AFL to it.
    170  *
    171  * -A resolver:<saddress>:<sport>:<raddress>:<rport>
    172  *
    173  * Here, <saddress>:<sport> is where named(resolver) is listening on.
    174  * <raddress>:<rport> is where the thread is supposed to setup the
    175  * authoritative server. This address should be configured via the root
    176  * zone to be the authoritiative server for aaaaaaaaaa.example.
    177  *
    178  * named(resolver) when being fuzzed will not cache answers.
    179  */
    180 static void *
    181 fuzz_thread_resolver(void *arg) {
    182 	char *sqtype, *shost, *sport, *rhost, *rport;
    183 	struct sockaddr_in servaddr, recaddr, recvaddr;
    184 	/*
    185 	 * Query for aaaaaaaaaa.example./A in wire format with RD=1,
    186 	 * EDNS and DO=1. 0x88, 0x0c at the start is the ID field which
    187 	 * will be updated for each query.
    188 	 */
    189 	char respacket[] = {
    190 		 0x88, 0x0c, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00,
    191 		 0x00, 0x00, 0x00, 0x01, 0x0a, 0x61, 0x61, 0x61,
    192 		 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x07,
    193 		 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00,
    194 		 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10,
    195 		 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
    196 	};
    197 	/*
    198 	 * Response for example./DNSKEY in wire format. Note that RRSIGs
    199 	 * were generated with this DNSKEY that are used as seeds for
    200 	 * AFL in the DNSSEC fuzzing job. So the DNSKEY content of this
    201 	 * message must not change, or the corresponding RRSIGs will
    202 	 * have to be updated. 0x8d, 0xf6 at the start is the ID field
    203 	 * which will be made to match the query.
    204 	 */
    205 	const isc_uint8_t dnskey_wf[] = {
    206 		0x8d, 0xf6, 0x84, 0x00, 0x00, 0x01, 0x00, 0x02,
    207 		0x00, 0x00, 0x00, 0x01, 0x07, 0x65, 0x78, 0x61,
    208 		0x6d, 0x70, 0x6c, 0x65, 0x00, 0x00, 0x30, 0x00,
    209 		0x01, 0xc0, 0x0c, 0x00, 0x30, 0x00, 0x01, 0x00,
    210 		0x00, 0x01, 0x2c, 0x01, 0x08, 0x01, 0x00, 0x03,
    211 		0x08, 0x03, 0x01, 0x00, 0x01, 0xbd, 0x81, 0xdc,
    212 		0x7f, 0x16, 0xd4, 0x81, 0x7c, 0x1f, 0x9f, 0x6a,
    213 		0x68, 0xdd, 0xd4, 0xda, 0x48, 0xd9, 0x1c, 0xbd,
    214 		0xa6, 0x46, 0x1a, 0xf0, 0xb4, 0xb9, 0xec, 0x3d,
    215 		0x6c, 0x0b, 0x57, 0xc7, 0xd6, 0x54, 0x66, 0xe6,
    216 		0x6c, 0xd5, 0x90, 0x3a, 0x78, 0x7d, 0x7f, 0x78,
    217 		0x80, 0xa2, 0x89, 0x61, 0x6d, 0x8a, 0x2b, 0xcd,
    218 		0x0a, 0x77, 0x7a, 0xad, 0xc9, 0x61, 0x53, 0x53,
    219 		0x8c, 0x99, 0x72, 0x86, 0x14, 0x74, 0x9c, 0x49,
    220 		0x2a, 0x47, 0x23, 0xf7, 0x02, 0x07, 0x73, 0x1c,
    221 		0x5c, 0x2e, 0xb4, 0x9a, 0xa4, 0xd7, 0x98, 0x42,
    222 		0xc3, 0xd2, 0xfe, 0xbf, 0xf3, 0xb3, 0x6a, 0x52,
    223 		0x92, 0xd5, 0xfa, 0x47, 0x00, 0xe3, 0xd9, 0x59,
    224 		0x31, 0x95, 0x48, 0x40, 0xfc, 0x06, 0x73, 0x90,
    225 		0xc6, 0x73, 0x96, 0xba, 0x29, 0x91, 0xe2, 0xac,
    226 		0xa3, 0xa5, 0x6d, 0x91, 0x6d, 0x52, 0xb9, 0x34,
    227 		0xba, 0x68, 0x4f, 0xad, 0xf0, 0xc3, 0xf3, 0x1d,
    228 		0x6d, 0x61, 0x76, 0xe5, 0x3d, 0xa3, 0x9b, 0x2a,
    229 		0x0c, 0x92, 0xb3, 0x78, 0x6b, 0xf1, 0x20, 0xd6,
    230 		0x90, 0xb7, 0xac, 0xe2, 0xf8, 0x2b, 0x94, 0x10,
    231 		0x79, 0xce, 0xa8, 0x60, 0x42, 0xea, 0x6a, 0x18,
    232 		0x2f, 0xc0, 0xd8, 0x05, 0x0a, 0x3b, 0x06, 0x0f,
    233 		0x02, 0x7e, 0xff, 0x33, 0x46, 0xee, 0xb6, 0x21,
    234 		0x25, 0x90, 0x63, 0x4b, 0x3b, 0x5e, 0xb2, 0x72,
    235 		0x3a, 0xcb, 0x91, 0x41, 0xf4, 0x20, 0x50, 0x78,
    236 		0x1c, 0x93, 0x95, 0xda, 0xfa, 0xae, 0x85, 0xc5,
    237 		0xd7, 0x6b, 0x92, 0x0c, 0x70, 0x6b, 0xe4, 0xb7,
    238 		0x29, 0x3a, 0x2e, 0x18, 0x88, 0x82, 0x33, 0x7c,
    239 		0xa8, 0xea, 0xb8, 0x31, 0x8f, 0xaf, 0x50, 0xc5,
    240 		0x9c, 0x08, 0x56, 0x8f, 0x09, 0x76, 0x4e, 0xdf,
    241 		0x97, 0x75, 0x9d, 0x00, 0x52, 0x7f, 0xdb, 0xec,
    242 		0x30, 0xcb, 0x1c, 0x4c, 0x2a, 0x21, 0x93, 0xc4,
    243 		0x6d, 0x85, 0xa9, 0x40, 0x3b, 0xc0, 0x0c, 0x00,
    244 		0x2e, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x01,
    245 		0x1b, 0x00, 0x30, 0x08, 0x01, 0x00, 0x00, 0x01,
    246 		0x2c, 0x67, 0x74, 0x85, 0x80, 0x58, 0xb3, 0xc5,
    247 		0x17, 0x36, 0x90, 0x07, 0x65, 0x78, 0x61, 0x6d,
    248 		0x70, 0x6c, 0x65, 0x00, 0x45, 0xac, 0xd3, 0x82,
    249 		0x69, 0xf3, 0x10, 0x3a, 0x97, 0x2c, 0x6a, 0xa9,
    250 		0x78, 0x99, 0xea, 0xb0, 0xcc, 0xf7, 0xaf, 0x33,
    251 		0x51, 0x5b, 0xdf, 0x77, 0x04, 0x18, 0x14, 0x99,
    252 		0x61, 0xeb, 0x8d, 0x76, 0x3f, 0xd1, 0x71, 0x14,
    253 		0x43, 0x80, 0x53, 0xc2, 0x3b, 0x9f, 0x09, 0x4f,
    254 		0xb3, 0x51, 0x04, 0x89, 0x0e, 0xc8, 0x54, 0x12,
    255 		0xcd, 0x07, 0x20, 0xbe, 0x94, 0xc2, 0xda, 0x99,
    256 		0xdd, 0x1e, 0xf8, 0xb0, 0x84, 0x2e, 0xf9, 0x19,
    257 		0x35, 0x36, 0xf5, 0xd0, 0x5d, 0x82, 0x18, 0x74,
    258 		0xa0, 0x00, 0xb6, 0x15, 0x57, 0x40, 0x5f, 0x78,
    259 		0x2d, 0x27, 0xac, 0xc7, 0x8a, 0x29, 0x55, 0xa9,
    260 		0xcd, 0xbc, 0xf7, 0x3e, 0xff, 0xae, 0x1a, 0x5a,
    261 		0x1d, 0xac, 0x0d, 0x78, 0x0e, 0x08, 0x33, 0x6c,
    262 		0x59, 0x70, 0x40, 0xb9, 0x65, 0xbd, 0x35, 0xbb,
    263 		0x9a, 0x70, 0xdc, 0x93, 0x66, 0xb0, 0xef, 0xfe,
    264 		0xf0, 0x32, 0xa6, 0xee, 0xb7, 0x03, 0x89, 0xa2,
    265 		0x4d, 0xe0, 0xf1, 0x20, 0xdf, 0x39, 0xe8, 0xe3,
    266 		0xcc, 0x95, 0xe9, 0x9a, 0xad, 0xbf, 0xbd, 0x7c,
    267 		0xf7, 0xd7, 0xde, 0x47, 0x9e, 0xf6, 0x17, 0xbb,
    268 		0x84, 0xa9, 0xed, 0xf2, 0x45, 0x61, 0x6d, 0x13,
    269 		0x0b, 0x06, 0x29, 0x50, 0xde, 0xfd, 0x42, 0xb0,
    270 		0x66, 0x2c, 0x1c, 0x2b, 0x63, 0xcb, 0x4e, 0xb9,
    271 		0x31, 0xc4, 0xea, 0xd2, 0x07, 0x3a, 0x08, 0x79,
    272 		0x19, 0x4b, 0x4c, 0x50, 0x97, 0x02, 0xd7, 0x26,
    273 		0x41, 0x2f, 0xdd, 0x57, 0xaa, 0xb0, 0xa0, 0x21,
    274 		0x4e, 0x74, 0xb6, 0x97, 0x4b, 0x8b, 0x09, 0x9c,
    275 		0x3d, 0x29, 0xfb, 0x12, 0x27, 0x47, 0x8f, 0xb8,
    276 		0xc5, 0x8e, 0x65, 0xcd, 0xca, 0x2f, 0xba, 0xf5,
    277 		0x3e, 0xec, 0x56, 0xc3, 0xc9, 0xa1, 0x62, 0x7d,
    278 		0xf2, 0x9f, 0x90, 0x16, 0x1d, 0xbf, 0x97, 0x28,
    279 		0xe1, 0x92, 0xb1, 0x53, 0xab, 0xc4, 0xe0, 0x99,
    280 		0xbb, 0x19, 0x90, 0x7c, 0x00, 0x00, 0x29, 0x10,
    281 		0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00
    282 	};
    283 
    284 	int sockfd;
    285 	int listenfd;
    286 	int loop;
    287 	isc_uint16_t qtype;
    288 	char *buf, *rbuf;
    289 	char *nameptr;
    290 	unsigned int i;
    291 	isc_uint8_t llen;
    292 	isc_uint64_t seed;
    293 
    294 	UNUSED(arg);
    295 
    296 	/*
    297 	 * Parse named -A argument in the "qtype:saddress:sport:raddress:rport"
    298 	 * syntax.  Due to the syntax used, this only supports IPv4 addresses.
    299 	 */
    300 	sqtype = strdup(named_g_fuzz_addr);
    301 	RUNTIME_CHECK(sqtype != NULL);
    302 
    303 	shost = strchr(sqtype, ':');
    304 	RUNTIME_CHECK(shost != NULL);
    305 	*shost = 0;
    306 	shost++;
    307 
    308 	sport = strchr(shost, ':');
    309 	RUNTIME_CHECK(sport != NULL);
    310 	*sport = 0;
    311 	sport++;
    312 
    313 	rhost = strchr(sport, ':');
    314 	RUNTIME_CHECK(rhost != NULL);
    315 	*rhost = 0;
    316 	rhost++;
    317 
    318 	rport = strchr(rhost, ':');
    319 	RUNTIME_CHECK(rport != NULL);
    320 	*rport = 0;
    321 	rport++;
    322 
    323 	/*
    324 	 * Patch in the qtype into the question section of respacket.
    325 	 */
    326 	qtype = atoi(sqtype);
    327 	respacket[32] = (qtype >> 8) & 0xff;
    328 	respacket[33] = qtype & 0xff;
    329 
    330 	memset(&servaddr, 0, sizeof (servaddr));
    331 	servaddr.sin_family = AF_INET;
    332 	RUNTIME_CHECK(inet_pton(AF_INET, shost, &servaddr.sin_addr) == 1);
    333 	servaddr.sin_port = htons(atoi(sport));
    334 
    335 	memset(&recaddr, 0, sizeof (recaddr));
    336 	recaddr.sin_family = AF_INET;
    337 	RUNTIME_CHECK(inet_pton(AF_INET, rhost, &recaddr.sin_addr) == 1);
    338 	recaddr.sin_port = htons(atoi(rport));
    339 
    340 	free(sqtype);
    341 
    342 	/*
    343 	 * Wait for named to start. This is set in run_server() in the
    344 	 * named thread.
    345 	 */
    346 	while (!named_g_run_done) {
    347 		usleep(10000);
    348 	}
    349 
    350 	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    351 	RUNTIME_CHECK(sockfd != -1);
    352 
    353 	listenfd = socket(AF_INET, SOCK_DGRAM, 0);
    354 	RUNTIME_CHECK(listenfd != -1);
    355 
    356 	RUNTIME_CHECK(bind(listenfd, (struct sockaddr *)&recaddr,
    357 			   sizeof(struct sockaddr_in)) == 0);
    358 
    359 	buf = malloc(65536);
    360 	rbuf = malloc(65536);
    361 	RUNTIME_CHECK(buf != NULL);
    362 	RUNTIME_CHECK(rbuf != NULL);
    363 
    364 	seed = 42;
    365 
    366 	/*
    367 	 * Processing fuzzed packets 100,000 times before shutting down
    368 	 * the app.
    369 	 */
    370 	for (loop = 0; loop < 100000; loop++) {
    371 		ssize_t length;
    372 		ssize_t sent;
    373 		unsigned short id;
    374 		socklen_t socklen;
    375 
    376 		memset(buf, 0, 12);
    377 		length = read(0, buf, 65536);
    378 		if (length <= 0) {
    379 			usleep(1000000);
    380 			continue;
    381 		}
    382 
    383 		if (length > 4096) {
    384 			if (getenv("AFL_CMIN")) {
    385 				free(buf);
    386 				free(rbuf);
    387 				close(sockfd);
    388 				close(listenfd);
    389 				named_server_flushonshutdown(named_g_server,
    390 							     ISC_FALSE);
    391 				isc_app_shutdown();
    392 				return (NULL);
    393 			}
    394 			raise(SIGSTOP);
    395 			continue;
    396 		}
    397 
    398 		if (length < 12) {
    399 		    length = 12;
    400 		}
    401 
    402 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    403 
    404 		ready = ISC_FALSE;
    405 
    406 		/* Use a unique query ID. */
    407 		seed = 1664525 * seed + 1013904223;
    408 		id = seed & 0xffff;
    409 		respacket[0] = (id >> 8) & 0xff;
    410 		respacket[1] = id & 0xff;
    411 
    412 		/*
    413 		 * Flush any pending data on the authoritative server.
    414 		 */
    415 		socklen = sizeof(recvaddr);
    416 		sent = recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT,
    417 			(struct sockaddr *) &recvaddr, &socklen);
    418 
    419 		/*
    420 		 * Send a fixed client query to named(resolver) of
    421 		 * aaaaaaaaaa.example./A. This is the starting query
    422 		 * driver.
    423 		 */
    424 		sent = sendto(sockfd, respacket, sizeof(respacket), 0,
    425 		       (struct sockaddr *) &servaddr, sizeof(servaddr));
    426 		RUNTIME_CHECK(sent == sizeof(respacket));
    427 
    428 		/*
    429 		 * named(resolver) will process the query above and send
    430 		 * an upstream query to the authoritative server. We
    431 		 * handle that here as the upstream authoritative server
    432 		 * on listenfd.
    433 		 */
    434 		socklen = sizeof(recvaddr);
    435 		sent = recvfrom(listenfd, rbuf, 65536, 0,
    436 				(struct sockaddr *) &recvaddr, &socklen);
    437 		RUNTIME_CHECK(sent > 0);
    438 
    439 		/*
    440 		 * Copy QID and set QR so that response is always
    441 		 * accepted by named(resolver).
    442 		 */
    443 		buf[0] = rbuf[0];
    444 		buf[1] = rbuf[1];
    445 		buf[2] |= 0x80;
    446 
    447 		/*
    448 		 * NOTE: We are not copying the QNAME or setting
    449 		 * rcode=NOERROR each time. So the resolver may fail the
    450 		 * client query (driver) / wander due to this. AA flag
    451 		 * may also not be set based on the contents of the AFL
    452 		 * fuzzed packet.
    453 		 */
    454 
    455 		/*
    456 		 * A hack - set QTYPE to the one from query so that we
    457 		 * can easily share packets between instances. If we
    458 		 * write over something else we'll get FORMERR anyway.
    459 		 */
    460 
    461 		/* Skip DNS header to get to the name */
    462 		nameptr = buf + 12;
    463 
    464 		/* Skip the name to get to the qtype */
    465 		i = 0;
    466 		while (((llen = nameptr[i]) != 0) &&
    467 		       (i < 255) &&
    468 		       (((nameptr + i + 1 + llen) - buf) < length))
    469 			i += 1 + llen;
    470 
    471 		if (i <= 255) {
    472 			nameptr += 1 + i;
    473 			/* Patch the qtype */
    474 			if ((nameptr - buf) < (length - 2)) {
    475 				*nameptr++ = (qtype >> 8) & 0xff;
    476 				*nameptr++ = qtype & 0xff;
    477 			}
    478 			/* Patch the qclass */
    479 			if ((nameptr - buf) < (length - 2)) {
    480 				*nameptr++ = 0;
    481 				*nameptr++ = 1;
    482 			}
    483 		}
    484 
    485 		/*
    486 		 * Send the reply to named(resolver).
    487 		 */
    488 		sent = sendto(listenfd, buf, length, 0,
    489 			      (struct sockaddr *) &recvaddr, sizeof(recvaddr));
    490 		RUNTIME_CHECK(sent == length);
    491 
    492 		/* We might get additional questions here (e.g. for CNAME). */
    493 		for (;;) {
    494 			fd_set fds;
    495 			struct timeval tv;
    496 			int rv;
    497 			int max;
    498 
    499 			FD_ZERO(&fds);
    500 			FD_SET(listenfd, &fds);
    501 			FD_SET(sockfd, &fds);
    502 			tv.tv_sec = 10;
    503 			tv.tv_usec = 0;
    504 			max = (listenfd > sockfd ? listenfd : sockfd)+1;
    505 
    506 			rv = select(max, &fds, NULL, NULL, &tv);
    507 			RUNTIME_CHECK(rv > 0);
    508 
    509 			if (FD_ISSET(sockfd, &fds)) {
    510 				/*
    511 				 * It's the reply from named(resolver)
    512 				 * to the client(query driver), so we're
    513 				 * done.
    514 				 */
    515 				recvfrom(sockfd, buf, 65536, 0, NULL, NULL);
    516 				break;
    517 			}
    518 
    519 			/*
    520 			 * We've got additional question (eg. due to
    521 			 * CNAME). Bounce it - setting QR flag and
    522 			 * NOERROR rcode and sending it back.
    523 			 */
    524 			length = recvfrom(listenfd, buf, 65536, 0,
    525 				   (struct sockaddr *) &recvaddr, &socklen);
    526 
    527 			/*
    528 			 * If this is a DNSKEY query, send the DNSKEY,
    529 			 * otherwise, bounce the query.
    530 			 */
    531 
    532 			/* Skip DNS header to get to the name */
    533 			nameptr = buf + 12;
    534 
    535 			/* Skip the name to get to the qtype */
    536 			i = 0;
    537 			while (((llen = nameptr[i]) != 0) &&
    538 			       (i < 255) &&
    539 			       (((nameptr + i + 1 + llen) - buf) < length))
    540 				i += 1 + llen;
    541 
    542 			if (i <= 255) {
    543 				nameptr += 1 + i;
    544 				/*
    545 				 * Patch in the DNSKEY reply without
    546 				 * touching the ID field. Note that we
    547 				 * don't compare the name in the
    548 				 * question section in the query, but we
    549 				 * don't expect to receive any query for
    550 				 * type DNSKEY but for the name
    551 				 * "example."
    552 				 */
    553 				if ((nameptr - buf) < (length - 2)) {
    554 					isc_uint8_t hb, lb;
    555 					hb = *nameptr++;
    556 					lb = *nameptr++;
    557 					qtype = (hb << 8) | lb;
    558 
    559 					if (qtype == 48) {
    560 						memmove(buf + 2, dnskey_wf + 2,
    561 							sizeof (dnskey_wf) - 2);
    562 						length = sizeof (dnskey_wf);
    563 					}
    564 				}
    565 			}
    566 
    567 			buf[2] |= 0x80;
    568 			buf[3] &= 0xF0;
    569 			sent = sendto(listenfd, buf, length, 0,
    570 				      (struct sockaddr *) &recvaddr,
    571 				      sizeof(recvaddr));
    572 			RUNTIME_CHECK(sent == length);
    573 		}
    574 
    575 		while (!ready)
    576 			pthread_cond_wait(&cond, &mutex);
    577 
    578 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    579 	}
    580 
    581 	free(buf);
    582 	close(sockfd);
    583 	close(listenfd);
    584 	named_server_flushonshutdown(named_g_server, ISC_FALSE);
    585 	isc_app_shutdown();
    586 
    587 	/*
    588 	 * This is here just for the signature, that's how AFL detects
    589 	 * if it's a 'persistent mode' binary. It has to occur somewhere
    590 	 * in the file, that's all. < wpk_> AFL checks the binary for
    591 	 * this signature ("##SIG_AFL_PERSISTENT##") and runs the binary
    592 	 * in persistent mode if it's present.
    593 	 */
    594 	__AFL_LOOP(0);
    595 
    596 	return (NULL);
    597 }
    598 
    599 /*
    600  * In "tcp:", "http:" and "rndc:" modes, this thread reads fuzzed query
    601  * blobs from AFL from standard input and sends it to the corresponding
    602  * TCP listening port of named (port 53 DNS, or the HTTP statistics
    603  * channels listener or the rndc port) that is passed in the -A
    604  * <mode>:<address>:<port> option. It can be used to test named from the
    605  * client side.
    606  */
    607 static void *
    608 fuzz_thread_tcp(void *arg) {
    609 	char *host;
    610 	char *port;
    611 	struct sockaddr_in servaddr;
    612 	int sockfd;
    613 	char *buf;
    614 	int loop;
    615 
    616 	UNUSED(arg);
    617 
    618 	/*
    619 	 * Parse named -A argument in the "address:port" syntax. Due to
    620 	 * the syntax used, this only supports IPv4 addresses.
    621 	 */
    622 	host = strdup(named_g_fuzz_addr);
    623 	RUNTIME_CHECK(host != NULL);
    624 
    625 	port = strchr(host, ':');
    626 	RUNTIME_CHECK(port != NULL);
    627 	*port = 0;
    628 	++port;
    629 
    630 	memset(&servaddr, 0, sizeof (servaddr));
    631 	servaddr.sin_family = AF_INET;
    632 	RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1);
    633 	servaddr.sin_port = htons(atoi(port));
    634 
    635 	free(host);
    636 
    637 	/*
    638 	 * Wait for named to start. This is set in run_server() in the
    639 	 * named thread.
    640 	 */
    641 	while (!named_g_run_done) {
    642 		usleep(10000);
    643 	}
    644 
    645 	buf = malloc(65539);
    646 	RUNTIME_CHECK(buf != NULL);
    647 
    648 	/*
    649 	 * Processing fuzzed packets 100,000 times before shutting down
    650 	 * the app.
    651 	 */
    652 	for (loop = 0; loop < 100000; loop++) {
    653 		ssize_t length;
    654 		ssize_t sent;
    655 		int yes;
    656 		int r;
    657 
    658 		if (named_g_fuzz_type == isc_fuzz_tcpclient) {
    659 			/*
    660 			 * To fuzz DNS TCP client we have to put 16-bit
    661 			 * message length preceding the start of packet.
    662 			 */
    663 			length = read(0, buf+2, 65535);
    664 			buf[0] = (length >> 8) & 0xff;
    665 			buf[1] = length & 0xff;
    666 			length += 2;
    667 		} else {
    668 			/*
    669 			 * Other types of TCP clients such as HTTP, etc.
    670 			 */
    671 			length = read(0, buf, 65535);
    672 		}
    673 		if (length <= 0) {
    674 			usleep(1000000);
    675 			continue;
    676 		}
    677 		if (named_g_fuzz_type == isc_fuzz_http) {
    678 			/*
    679 			 * This guarantees that the request will be
    680 			 * processed.
    681 			 */
    682 			INSIST(length <= 65535);
    683 			buf[length++]='\r';
    684 			buf[length++]='\n';
    685 			buf[length++]='\r';
    686 			buf[length++]='\n';
    687 		}
    688 
    689 		RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    690 
    691 		ready = ISC_FALSE;
    692 		yes = 1;
    693 		sockfd = socket(AF_INET, SOCK_STREAM, 0);
    694 
    695 		RUNTIME_CHECK(sockfd != -1);
    696 		RUNTIME_CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
    697 					 &yes, sizeof(int)) == 0);
    698 
    699 		do {
    700 			r = connect(sockfd, (struct sockaddr*)&servaddr,
    701 				    sizeof(servaddr));
    702 			if (r != 0)
    703 				usleep(10000);
    704 		} while (r != 0);
    705 
    706 		/*
    707 		 * Send the fuzzed query blob to the target server.
    708 		 */
    709 		sent = write(sockfd, buf, length);
    710 		RUNTIME_CHECK(sent == length);
    711 
    712 		close(sockfd);
    713 
    714 		while (!ready)
    715 			pthread_cond_wait(&cond, &mutex);
    716 
    717 		RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    718 	}
    719 
    720 	free(buf);
    721 	close(sockfd);
    722 	named_server_flushonshutdown(named_g_server, ISC_FALSE);
    723 	isc_app_shutdown();
    724 
    725 	return (NULL);
    726 }
    727 
    728 #endif /* ENABLE_AFL */
    729 
    730 /*
    731  * named has finished processing a message and has sent the
    732  * reply. Signal the fuzz thread using the condition variable, to read
    733  * and process the next item from AFL.
    734  */
    735 void
    736 named_fuzz_notify(void) {
    737 #ifdef ENABLE_AFL
    738 	if (getenv("AFL_CMIN")) {
    739 		named_server_flushonshutdown(named_g_server, ISC_FALSE);
    740 		isc_app_shutdown();
    741 		return;
    742 	}
    743 
    744 	raise(SIGSTOP);
    745 
    746 	RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
    747 
    748 	ready = ISC_TRUE;
    749 
    750 	RUNTIME_CHECK(pthread_cond_signal(&cond) == 0);
    751 	RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0);
    752 #endif /* ENABLE_AFL */
    753 }
    754 
    755 void
    756 named_fuzz_setup(void) {
    757 #ifdef ENABLE_AFL
    758 	if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) {
    759 		pthread_t thread;
    760 		void *(fn) = NULL;
    761 
    762 		switch (named_g_fuzz_type) {
    763 		case isc_fuzz_client:
    764 			fn = fuzz_thread_client;
    765 			break;
    766 
    767 		case isc_fuzz_http:
    768 		case isc_fuzz_tcpclient:
    769 		case isc_fuzz_rndc:
    770 			fn = fuzz_thread_tcp;
    771 			break;
    772 
    773 		case isc_fuzz_resolver:
    774 			fn = fuzz_thread_resolver;
    775 			break;
    776 
    777 		default:
    778 			RUNTIME_CHECK(fn != NULL);
    779 		}
    780 
    781 		RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0);
    782 		RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0);
    783 		RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0);
    784 	}
    785 #endif /* ENABLE_AFL */
    786 }
    787