xref: /openbsd/regress/lib/libssl/dtls/dtlstest.c (revision 771fbea0)
1 /* $OpenBSD: dtlstest.c,v 1.8 2021/05/03 23:44:05 inoguchi Exp $ */
2 /*
3  * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20 
21 #include <err.h>
22 #include <limits.h>
23 #include <poll.h>
24 #include <unistd.h>
25 
26 #include <openssl/bio.h>
27 #include <openssl/err.h>
28 #include <openssl/ssl.h>
29 
30 const char *server_ca_file;
31 const char *server_cert_file;
32 const char *server_key_file;
33 
34 char dtls_cookie[32];
35 
36 int debug = 0;
37 
38 static void
39 hexdump(const unsigned char *buf, size_t len)
40 {
41 	size_t i;
42 
43 	for (i = 1; i <= len; i++)
44 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
45 
46 	if (len % 8)
47 		fprintf(stderr, "\n");
48 }
49 
50 #define BIO_C_DROP_PACKET	1000
51 #define BIO_C_DROP_RANDOM	1001
52 
53 struct bio_packet_monkey_ctx {
54 	unsigned int drop_rand;
55 	unsigned int drop_mask;
56 };
57 
58 static int
59 bio_packet_monkey_new(BIO *bio)
60 {
61 	struct bio_packet_monkey_ctx *ctx;
62 
63 	if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
64 		return 0;
65 
66 	bio->flags = 0;
67 	bio->init = 1;
68 	bio->num = 0;
69 	bio->ptr = ctx;
70 
71 	return 1;
72 }
73 
74 static int
75 bio_packet_monkey_free(BIO *bio)
76 {
77 	struct bio_packet_monkey_ctx *ctx;
78 
79 	if (bio == NULL)
80 		return 1;
81 
82 	ctx = bio->ptr;
83 	free(ctx);
84 
85 	return 1;
86 }
87 
88 static long
89 bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr)
90 {
91 	struct bio_packet_monkey_ctx *ctx;
92 
93 	ctx = bio->ptr;
94 
95 	switch (cmd) {
96 	case BIO_C_DROP_PACKET:
97 		if (num < 1 || num > 31)
98 			return 0;
99 		ctx->drop_mask |= 1 << ((unsigned int)num - 1);
100 		return 1;
101 
102 	case BIO_C_DROP_RANDOM:
103 		if (num < 0 || (size_t)num > UINT_MAX)
104 			return 0;
105 		ctx->drop_rand = (unsigned int)num;
106 		return 1;
107 	}
108 
109 	if (bio->next_bio == NULL)
110 		return 0;
111 
112 	return BIO_ctrl(bio->next_bio, cmd, num, ptr);
113 }
114 
115 static int
116 bio_packet_monkey_read(BIO *bio, char *out, int out_len)
117 {
118 	struct bio_packet_monkey_ctx *ctx = bio->ptr;
119 	int ret;
120 
121 	if (ctx == NULL || bio->next_bio == NULL)
122 		return 0;
123 
124 	ret = BIO_read(bio->next_bio, out, out_len);
125 
126 	BIO_clear_retry_flags(bio);
127 	if (ret <= 0 && BIO_should_retry(bio->next_bio))
128 		BIO_set_retry_read(bio);
129 
130 	return ret;
131 }
132 
133 static int
134 bio_packet_monkey_write(BIO *bio, const char *in, int in_len)
135 {
136 	struct bio_packet_monkey_ctx *ctx = bio->ptr;
137 	int drop = 0;
138 	int ret;
139 
140 	if (ctx == NULL || bio->next_bio == NULL)
141 		return 0;
142 
143 	if (ctx->drop_rand > 0) {
144 		drop = arc4random_uniform(ctx->drop_rand) == 0;
145 	} else if (ctx->drop_mask > 0) {
146 		drop = ctx->drop_mask & 1;
147 		ctx->drop_mask >>= 1;
148 	}
149 	if (debug) {
150 		fprintf(stderr, "DEBUG: %s packet...\n",
151 		    drop ? "dropping" : "writing");
152 		if (debug > 1)
153 			hexdump(in, in_len);
154 	}
155 	if (drop)
156 		return in_len;
157 
158 	ret = BIO_write(bio->next_bio, in, in_len);
159 
160 	BIO_clear_retry_flags(bio);
161 	if (ret <= 0 && BIO_should_retry(bio->next_bio))
162 		BIO_set_retry_write(bio);
163 
164 	return ret;
165 }
166 
167 static int
168 bio_packet_monkey_puts(BIO *bio, const char *str)
169 {
170 	return bio_packet_monkey_write(bio, str, strlen(str));
171 }
172 
173 static const BIO_METHOD bio_packet_monkey = {
174 	.type = BIO_TYPE_BUFFER,
175 	.name = "packet monkey",
176 	.bread = bio_packet_monkey_read,
177 	.bwrite = bio_packet_monkey_write,
178 	.bputs = bio_packet_monkey_puts,
179 	.ctrl = bio_packet_monkey_ctrl,
180 	.create = bio_packet_monkey_new,
181 	.destroy = bio_packet_monkey_free
182 };
183 
184 static const BIO_METHOD *
185 BIO_f_packet_monkey(void)
186 {
187 	return &bio_packet_monkey;
188 }
189 
190 static BIO *
191 BIO_new_packet_monkey(void)
192 {
193 	return BIO_new(BIO_f_packet_monkey());
194 }
195 
196 static int
197 BIO_packet_monkey_drop(BIO *bio, int num)
198 {
199 	return BIO_ctrl(bio, BIO_C_DROP_PACKET, num, NULL);
200 }
201 
202 #if 0
203 static int
204 BIO_packet_monkey_drop_random(BIO *bio, int num)
205 {
206 	return BIO_ctrl(bio, BIO_C_DROP_RANDOM, num, NULL);
207 }
208 #endif
209 
210 static int
211 datagram_pair(int *client_sock, int *server_sock,
212     struct sockaddr_in *server_sin)
213 {
214 	struct sockaddr_in sin;
215 	socklen_t sock_len;
216 	int cs = -1, ss = -1;
217 
218 	memset(&sin, 0, sizeof(sin));
219 	sin.sin_family = AF_INET;
220 	sin.sin_port = 0;
221 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
222 
223 	if ((ss = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
224 		err(1, "server socket");
225 	if (bind(ss, (struct sockaddr *)&sin, sizeof(sin)) == -1)
226 		err(1, "server bind");
227 	sock_len = sizeof(sin);
228 	if (getsockname(ss, (struct sockaddr *)&sin, &sock_len) == -1)
229 		err(1, "server getsockname");
230 
231 	if ((cs = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
232 		err(1, "client socket");
233 	if (connect(cs, (struct sockaddr *)&sin, sizeof(sin)) == -1)
234 		err(1, "client connect");
235 
236 	*client_sock = cs;
237 	*server_sock = ss;
238 	memcpy(server_sin, &sin, sizeof(sin));
239 
240 	return 1;
241 }
242 
243 static int
244 poll_timeout(SSL *client, SSL *server)
245 {
246 	int client_timeout = 0, server_timeout = 0;
247 	struct timeval timeout;
248 
249 	if (DTLSv1_get_timeout(client, &timeout))
250 		client_timeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
251 
252 	if (DTLSv1_get_timeout(server, &timeout))
253 		server_timeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
254 
255 	if (client_timeout <= 0)
256 		return server_timeout;
257 	if (client_timeout > 0 && server_timeout <= 0)
258 		return client_timeout;
259 	if (client_timeout < server_timeout)
260 		return client_timeout;
261 
262 	return server_timeout;
263 }
264 
265 static int
266 dtls_cookie_generate(SSL *ssl, unsigned char *cookie,
267     unsigned int *cookie_len)
268 {
269 	arc4random_buf(dtls_cookie, sizeof(dtls_cookie));
270 	memcpy(cookie, dtls_cookie, sizeof(dtls_cookie));
271 	*cookie_len = sizeof(dtls_cookie);
272 
273 	return 1;
274 }
275 
276 static int
277 dtls_cookie_verify(SSL *ssl, const unsigned char *cookie,
278     unsigned int cookie_len)
279 {
280 	return cookie_len == sizeof(dtls_cookie) &&
281 	    memcmp(cookie, dtls_cookie, sizeof(dtls_cookie)) == 0;
282 }
283 
284 static void
285 dtls_info_callback(const SSL *ssl, int type, int val)
286 {
287 	/*
288 	 * Squeals ahead... remove the bbio from the info callback, so we can
289 	 * drop specific messages. Ideally this would be an option for the SSL.
290 	 */
291 	if (ssl->wbio == ssl->bbio)
292 		((SSL *)ssl)->wbio = BIO_pop(ssl->wbio);
293 }
294 
295 static SSL *
296 dtls_client(int sock, struct sockaddr_in *server_sin, long mtu)
297 {
298 	SSL_CTX *ssl_ctx = NULL;
299 	SSL *ssl = NULL;
300 	BIO *bio = NULL;
301 
302 	if ((bio = BIO_new_dgram(sock, BIO_NOCLOSE)) == NULL)
303 		errx(1, "client bio");
304 	if (!BIO_socket_nbio(sock, 1))
305 		errx(1, "client nbio");
306 	if (!BIO_ctrl_set_connected(bio, 1, server_sin))
307 		errx(1, "client set connected");
308 
309 	if ((ssl_ctx = SSL_CTX_new(DTLS_method())) == NULL)
310 		errx(1, "client context");
311 	SSL_CTX_set_read_ahead(ssl_ctx, 1);
312 
313 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
314 		errx(1, "client ssl");
315 
316 	SSL_set_bio(ssl, bio, bio);
317 	bio = NULL;
318 
319 	if (mtu > 0) {
320 		SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU);
321 		SSL_set_mtu(ssl, mtu);
322 	}
323 
324 	SSL_CTX_free(ssl_ctx);
325 	BIO_free(bio);
326 
327 	return ssl;
328 }
329 
330 static SSL *
331 dtls_server(int sock, long options, long mtu)
332 {
333 	SSL_CTX *ssl_ctx = NULL;
334 	SSL *ssl = NULL;
335 	BIO *bio = NULL;
336 
337 	if ((bio = BIO_new_dgram(sock, BIO_NOCLOSE)) == NULL)
338 		errx(1, "server bio");
339 	if (!BIO_socket_nbio(sock, 1))
340 		errx(1, "server nbio");
341 
342 	if ((ssl_ctx = SSL_CTX_new(DTLS_method())) == NULL)
343 		errx(1, "server context");
344 
345 	SSL_CTX_set_cookie_generate_cb(ssl_ctx, dtls_cookie_generate);
346 	SSL_CTX_set_cookie_verify_cb(ssl_ctx, dtls_cookie_verify);
347 	SSL_CTX_set_dh_auto(ssl_ctx, 2);
348 	SSL_CTX_set_options(ssl_ctx, options);
349 	SSL_CTX_set_read_ahead(ssl_ctx, 1);
350 
351 	if (SSL_CTX_use_certificate_file(ssl_ctx, server_cert_file,
352 	    SSL_FILETYPE_PEM) != 1) {
353 		fprintf(stderr, "FAIL: Failed to load server certificate");
354 		goto failure;
355 	}
356 	if (SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key_file,
357 	    SSL_FILETYPE_PEM) != 1) {
358 		fprintf(stderr, "FAIL: Failed to load server private key");
359 		goto failure;
360 	}
361 
362 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
363 		errx(1, "server ssl");
364 
365 	SSL_set_bio(ssl, bio, bio);
366 	bio = NULL;
367 
368 	if (mtu > 0) {
369 		SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU);
370 		SSL_set_mtu(ssl, mtu);
371 	}
372 
373  failure:
374 	SSL_CTX_free(ssl_ctx);
375 	BIO_free(bio);
376 
377 	return ssl;
378 }
379 
380 static int
381 ssl_error(SSL *ssl, const char *name, const char *desc, int ssl_ret,
382     short *events)
383 {
384 	int ssl_err;
385 
386 	ssl_err = SSL_get_error(ssl, ssl_ret);
387 
388 	if (ssl_err == SSL_ERROR_WANT_READ) {
389 		*events = POLLIN;
390 	} else if (ssl_err == SSL_ERROR_WANT_WRITE) {
391 		*events = POLLOUT;
392 	} else if (ssl_err == SSL_ERROR_SYSCALL && errno == 0) {
393 		/* Yup, this is apparently a thing... */
394 	} else {
395 		fprintf(stderr, "FAIL: %s %s failed - ssl err = %d, errno = %d\n",
396 		    name, desc, ssl_err, errno);
397 		ERR_print_errors_fp(stderr);
398 		return 0;
399 	}
400 
401 	return 1;
402 }
403 
404 static int
405 do_connect(SSL *ssl, const char *name, int *done, short *events)
406 {
407 	int ssl_ret;
408 
409 	if ((ssl_ret = SSL_connect(ssl)) == 1) {
410 		fprintf(stderr, "INFO: %s connect done\n", name);
411 		*done = 1;
412 		return 1;
413 	}
414 
415 	return ssl_error(ssl, name, "connect", ssl_ret, events);
416 }
417 
418 static int
419 do_accept(SSL *ssl, const char *name, int *done, short *events)
420 {
421 	int ssl_ret;
422 
423 	if ((ssl_ret = SSL_accept(ssl)) == 1) {
424 		fprintf(stderr, "INFO: %s accept done\n", name);
425 		*done = 1;
426 		return 1;
427 	}
428 
429 	return ssl_error(ssl, name, "accept", ssl_ret, events);
430 }
431 
432 static int
433 do_read(SSL *ssl, const char *name, int *done, short *events)
434 {
435 	uint8_t buf[512];
436 	int ssl_ret;
437 
438 	if ((ssl_ret = SSL_read(ssl, buf, sizeof(buf))) > 0) {
439 		fprintf(stderr, "INFO: %s read done\n", name);
440 		if (debug > 1)
441 			hexdump(buf, ssl_ret);
442 		*done = 1;
443 		return 1;
444 	}
445 
446 	return ssl_error(ssl, name, "read", ssl_ret, events);
447 }
448 
449 static int
450 do_write(SSL *ssl, const char *name, int *done, short *events)
451 {
452 	const uint8_t buf[] = "Hello, World!\n";
453 	int ssl_ret;
454 
455 	if ((ssl_ret = SSL_write(ssl, buf, sizeof(buf))) > 0) {
456 		fprintf(stderr, "INFO: %s write done\n", name);
457 		*done = 1;
458 		return 1;
459 	}
460 
461 	return ssl_error(ssl, name, "write", ssl_ret, events);
462 }
463 
464 static int
465 do_shutdown(SSL *ssl, const char *name, int *done, short *events)
466 {
467 	int ssl_ret;
468 
469 	ssl_ret = SSL_shutdown(ssl);
470 	if (ssl_ret == 1) {
471 		fprintf(stderr, "INFO: %s shutdown done\n", name);
472 		*done = 1;
473 		return 1;
474 	}
475 	return ssl_error(ssl, name, "shutdown", ssl_ret, events);
476 }
477 
478 typedef int (*ssl_func)(SSL *ssl, const char *name, int *done, short *events);
479 
480 static int
481 do_client_server_loop(SSL *client, ssl_func client_func, SSL *server,
482     ssl_func server_func, struct pollfd pfd[2])
483 {
484 	int client_done = 0, server_done = 0;
485 	int i = 0;
486 
487 	pfd[0].revents = POLLIN;
488 	pfd[1].revents = POLLIN;
489 
490 	do {
491 		if (!client_done) {
492 			if (debug)
493 				fprintf(stderr, "DEBUG: client loop\n");
494 			if (DTLSv1_handle_timeout(client) > 0)
495 				fprintf(stderr, "INFO: client timeout\n");
496 			if (!client_func(client, "client", &client_done,
497 			    &pfd[0].events))
498 				return 0;
499 			if (client_done)
500 				pfd[0].events = 0;
501 		}
502 		if (!server_done) {
503 			if (debug)
504 				fprintf(stderr, "DEBUG: server loop\n");
505 			if (DTLSv1_handle_timeout(server) > 0)
506 				fprintf(stderr, "INFO: server timeout\n");
507 			if (!server_func(server, "server", &server_done,
508 			    &pfd[1].events))
509 				return 0;
510 			if (server_done)
511 				pfd[1].events = 0;
512 		}
513 		if (poll(pfd, 2, poll_timeout(client, server)) == -1)
514 			err(1, "poll");
515 
516 	} while (i++ < 100 && (!client_done || !server_done));
517 
518 	if (!client_done || !server_done)
519 		fprintf(stderr, "FAIL: gave up\n");
520 
521 	return client_done && server_done;
522 }
523 
524 #define MAX_PACKET_DROPS 32
525 
526 struct dtls_test {
527 	const unsigned char *desc;
528 	long mtu;
529 	long ssl_options;
530 	int client_bbio_off;
531 	int server_bbio_off;
532 	uint8_t client_drops[MAX_PACKET_DROPS];
533 	uint8_t server_drops[MAX_PACKET_DROPS];
534 };
535 
536 static const struct dtls_test dtls_tests[] = {
537 	{
538 		.desc = "DTLS without cookies",
539 		.ssl_options = 0,
540 	},
541 	{
542 		.desc = "DTLS with cookies",
543 		.ssl_options = SSL_OP_COOKIE_EXCHANGE,
544 	},
545 	{
546 		.desc = "DTLS with low MTU",
547 		.mtu = 256,
548 		.ssl_options = 0,
549 	},
550 	{
551 		.desc = "DTLS with low MTU and cookies",
552 		.mtu = 256,
553 		.ssl_options = SSL_OP_COOKIE_EXCHANGE,
554 	},
555 	{
556 		.desc = "DTLS with dropped server response",
557 		.ssl_options = 0,
558 		.server_drops = { 1 },
559 	},
560 	{
561 		.desc = "DTLS with two dropped server responses",
562 		.ssl_options = 0,
563 		.server_drops = { 1, 2 },
564 	},
565 	{
566 		.desc = "DTLS with dropped ServerHello",
567 		.ssl_options = SSL_OP_NO_TICKET,
568 		.server_bbio_off = 1,
569 		.server_drops = { 1 },
570 	},
571 	{
572 		.desc = "DTLS with dropped server Certificate",
573 		.ssl_options = SSL_OP_NO_TICKET,
574 		.server_bbio_off = 1,
575 		.server_drops = { 2 },
576 	},
577 	{
578 		.desc = "DTLS with dropped ServerKeyExchange",
579 		.ssl_options = SSL_OP_NO_TICKET,
580 		.server_bbio_off = 1,
581 		.server_drops = { 3 },
582 	},
583 	{
584 		.desc = "DTLS with dropped ServerHelloDone",
585 		.ssl_options = SSL_OP_NO_TICKET,
586 		.server_bbio_off = 1,
587 		.server_drops = { 4 },
588 	},
589 #if 0
590 	/*
591 	 * These two result in the server accept completing and the
592 	 * client looping on a timeout. Presumably the server should not
593 	 * complete until the client Finished is received...
594 	 */
595 	{
596 		.desc = "DTLS with dropped server CCS",
597 		.ssl_options = 0,
598 		.server_bbio_off = 1,
599 		.server_drops = { 5 },
600 	},
601 	{
602 		.desc = "DTLS with dropped server Finished",
603 		.ssl_options = 0,
604 		.server_bbio_off = 1,
605 		.server_drops = { 6 },
606 	},
607 #endif
608 	{
609 		.desc = "DTLS with dropped ClientKeyExchange",
610 		.ssl_options = 0,
611 		.client_bbio_off = 1,
612 		.client_drops = { 2 },
613 	},
614 	{
615 		.desc = "DTLS with dropped client CCS",
616 		.ssl_options = 0,
617 		.client_bbio_off = 1,
618 		.client_drops = { 3 },
619 	},
620 	{
621 		.desc = "DTLS with dropped client Finished",
622 		.ssl_options = 0,
623 		.client_bbio_off = 1,
624 		.client_drops = { 4 },
625 	},
626 };
627 
628 #define N_DTLS_TESTS (sizeof(dtls_tests) / sizeof(*dtls_tests))
629 
630 static void
631 dtlstest_packet_monkey(SSL *ssl, const uint8_t drops[])
632 {
633 	BIO *bio_monkey;
634 	BIO *bio;
635 	int i;
636 
637 	if ((bio_monkey = BIO_new_packet_monkey()) == NULL)
638 		errx(1, "packet monkey");
639 
640 	for (i = 0; i < MAX_PACKET_DROPS; i++) {
641 		if (drops[i] == 0)
642 			break;
643 		if (!BIO_packet_monkey_drop(bio_monkey, drops[i]))
644 			errx(1, "drop failure");
645 	}
646 
647 	if ((bio = SSL_get_wbio(ssl)) == NULL)
648 		errx(1, "SSL has NULL bio");
649 
650 	BIO_up_ref(bio);
651 	bio = BIO_push(bio_monkey, bio);
652 
653 	SSL_set_bio(ssl, bio, bio);
654 }
655 
656 static int
657 dtlstest(const struct dtls_test *dt)
658 {
659 	SSL *client = NULL, *server = NULL;
660 	struct sockaddr_in server_sin;
661 	struct pollfd pfd[2];
662 	int client_sock = -1;
663 	int server_sock = -1;
664 	int failed = 1;
665 
666 	fprintf(stderr, "\n== Testing %s... ==\n", dt->desc);
667 
668 	if (!datagram_pair(&client_sock, &server_sock, &server_sin))
669 		goto failure;
670 
671 	if ((client = dtls_client(client_sock, &server_sin, dt->mtu)) == NULL)
672 		goto failure;
673 	if ((server = dtls_server(server_sock, dt->ssl_options, dt->mtu)) == NULL)
674 		goto failure;
675 
676 	if (dt->client_bbio_off)
677 		SSL_set_info_callback(client, dtls_info_callback);
678 	if (dt->server_bbio_off)
679 		SSL_set_info_callback(server, dtls_info_callback);
680 
681 	dtlstest_packet_monkey(client, dt->client_drops);
682 	dtlstest_packet_monkey(server, dt->server_drops);
683 
684 	pfd[0].fd = client_sock;
685 	pfd[0].events = POLLOUT;
686 	pfd[1].fd = server_sock;
687 	pfd[1].events = POLLIN;
688 
689 	if (!do_client_server_loop(client, do_connect, server, do_accept, pfd)) {
690 		fprintf(stderr, "FAIL: client and server handshake failed\n");
691 		goto failure;
692 	}
693 
694 	pfd[0].events = POLLIN;
695 	pfd[1].events = POLLOUT;
696 
697 	if (!do_client_server_loop(client, do_read, server, do_write, pfd)) {
698 		fprintf(stderr, "FAIL: client read and server write I/O failed\n");
699 		goto failure;
700 	}
701 
702 	pfd[0].events = POLLOUT;
703 	pfd[1].events = POLLIN;
704 
705 	if (!do_client_server_loop(client, do_write, server, do_read, pfd)) {
706 		fprintf(stderr, "FAIL: client write and server read I/O failed\n");
707 		goto failure;
708 	}
709 
710 	pfd[0].events = POLLOUT;
711 	pfd[1].events = POLLOUT;
712 
713 	if (!do_client_server_loop(client, do_shutdown, server, do_shutdown, pfd)) {
714 		fprintf(stderr, "FAIL: client and server shutdown failed\n");
715 		goto failure;
716 	}
717 
718 	fprintf(stderr, "INFO: Done!\n");
719 
720 	failed = 0;
721 
722  failure:
723 	if (client_sock != -1)
724 		close(client_sock);
725 	if (server_sock != -1)
726 		close(server_sock);
727 
728 	SSL_free(client);
729 	SSL_free(server);
730 
731 	return failed;
732 }
733 
734 int
735 main(int argc, char **argv)
736 {
737 	int failed = 0;
738 	size_t i;
739 
740 	if (argc != 4) {
741 		fprintf(stderr, "usage: %s keyfile certfile cafile\n",
742 		    argv[0]);
743 		exit(1);
744 	}
745 
746 	server_key_file = argv[1];
747 	server_cert_file = argv[2];
748 	server_ca_file = argv[3];
749 
750 	for (i = 0; i < N_DTLS_TESTS; i++)
751 		failed |= dtlstest(&dtls_tests[i]);
752 
753 	return failed;
754 }
755