xref: /minix/minix/tests/test83.c (revision 60299d87)
1 /*
2  * test83: test bad network packets
3  */
4 
5 #define DEBUG 0
6 
7 #if DEBUG
8 #define dbgprintf(...)	do {						\
9 				struct timeval time = { };		\
10 				gettimeofday(&time, NULL);		\
11 				fprintf(stderr, "[%2d:%.2d:%.2d.%.6d p%d %s:%d] ", \
12 					(int) ((time.tv_sec / 3600) % 24), \
13 					(int) ((time.tv_sec / 60) % 60), \
14 					(int) (time.tv_sec % 60),	\
15 					time.tv_usec,			\
16 					getpid(),			\
17 					__FUNCTION__,			\
18 					__LINE__);			\
19 				fprintf(stderr, __VA_ARGS__);		\
20 				fflush(stderr);				\
21 			} while (0)
22 #else
23 #define	dbgprintf(...)
24 #endif
25 
26 #include <arpa/inet.h>
27 #include <assert.h>
28 #include <fcntl.h>
29 #include <netinet/in.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/time.h>
39 #include <sys/wait.h>
40 
41 #include "common.h"
42 
43 int max_error = 100;
44 
45 /* https://tools.ietf.org/html/rfc791 */
46 struct header_ip {
47 	uint8_t  ver_ihl; /* Version (4 bits) + IHL (4 bits) */
48 	uint8_t  tos;     /* Type of Service */
49 	uint16_t len;     /* Total Length */
50 	uint16_t id;      /* Identification */
51 	uint16_t fl_fo;   /* Flags (3 bits) + Fragment Offset (13 bits) */
52 	uint8_t  ttl;     /* Time to Live */
53 	uint8_t  prot;    /* Protocol */
54 	uint16_t cs;      /* Header Checksum */
55 	uint32_t src;     /* Source Address */
56 	uint32_t dst;     /* Destination Address */
57 	uint8_t  opt[16]; /* Options  */
58 };
59 #define IP_FLAG_EVIL	(1 << 2)
60 #define IP_FLAG_DF	(1 << 1)
61 #define IP_FLAG_MF	(1 << 0)
62 
63 /* https://tools.ietf.org/html/rfc790 */
64 #define IP_PROT_ICMP	1
65 #define IP_PROT_TCP	6
66 #define IP_PROT_UDP	17
67 
68 /* https://tools.ietf.org/html/rfc768 */
69 struct header_udp {
70 	uint16_t src; /* Source Port */
71 	uint16_t dst; /* Destination Port */
72 	uint16_t len; /* Length */
73 	uint16_t cs;  /* Checksum */
74 };
75 
76 struct header_udp_pseudo {
77 	uint32_t src;
78 	uint32_t dst;
79 	uint8_t  zero;
80 	uint8_t  prot;
81 	uint16_t len;
82 };
83 
84 /* https://tools.ietf.org/html/rfc793 */
85 struct header_tcp {
86 	uint16_t src;     /* Source Port */
87 	uint16_t dst;     /* Destination Port */
88 	uint32_t seq;     /* Sequence Number */
89 	uint32_t ack;     /* Acknowledgment Number */
90 	uint8_t  doff;    /* Data Offset */
91 	uint8_t  fl;      /* Flags */
92 	uint16_t win;     /* Window */
93 	uint16_t cs;      /* Checksum */
94 	uint16_t uptr;    /* Urgent Pointer */
95 	uint8_t  opt[16]; /* Options  */
96 };
97 #define TCP_FLAG_URG	(1 << 5)
98 #define TCP_FLAG_ACK	(1 << 4)
99 #define TCP_FLAG_PSH	(1 << 3)
100 #define TCP_FLAG_RST	(1 << 2)
101 #define TCP_FLAG_SYN	(1 << 1)
102 #define TCP_FLAG_FIN	(1 << 0)
103 
104 #define PORT_BASE	12345
105 #define PORT_COUNT_TCP	4
106 #define PORT_COUNT_UDP	2
107 #define PORT_COUNT	(PORT_COUNT_TCP + PORT_COUNT_UDP)
108 
109 #define PORT_BASE_SRC	(PORT_BASE + PORT_COUNT)
110 #define PORT_COUNT_SRC	79
111 
112 #define PAYLOADSIZE_COUNT 6
113 static const size_t payloadsizes[] = {
114 	0,
115 	1,
116 	100,
117 	1024,
118 	2345,
119 	65535 - sizeof(struct header_ip) - sizeof(struct header_udp),
120 };
121 
122 /* In its current configuration, this test uses the loopback interface only. */
123 static uint32_t addrsrc = INADDR_LOOPBACK; /* 127.0.0.1 (localhost) */
124 static uint32_t addrdst = INADDR_LOOPBACK; /* 127.0.0.1 (localhost) */
125 static uint32_t addrs[] = {
126 	INADDR_LOOPBACK, /* 127.0.0.1 (localhost) */
127 };
128 
129 #define CLOSE(fd) do { assert(fd >= 0); if (close((fd)) != 0) efmt("close failed"); } while (0);
130 enum server_action {
131 	sa_close,
132 	sa_read,
133 	sa_selectr,
134 	sa_selectrw,
135 	sa_write,
136 };
137 static int server_done;
138 
139 static void server_alarm(int seconds);
140 
141 static char *sigstr_cat(char *p, const char *s) {
142 	size_t slen = strlen(s);
143 	memcpy(p, s, slen);
144 	return p + slen;
145 }
146 
147 static char *sigstr_itoa(char *p, unsigned long n) {
148 	unsigned digit;
149 	unsigned long factor = 1000000000UL;
150 	int first = 1;
151 
152 	while (factor > 0) {
153 		digit = (n / factor) % 10;
154 		if (!first || digit || factor == 1) {
155 			*(p++) = digit + '0';
156 			first = 0;
157 		}
158 		factor /= 10;
159 	}
160 	return p;
161 }
162 
163 #if 0
164 static void dbgprintdata(const void *data, size_t size) {
165 	size_t addr;
166 	const unsigned char *p = data;
167 
168 	for (addr = 0; addr < size; addr++) {
169 		if (addr % 16 == 0) {
170 			if (addr > 0) fprintf(stderr, "\n");
171 			fprintf(stderr, "%.4zx", addr);
172 		}
173 		fprintf(stderr, " %.2x", p[addr]);
174 	}
175 	fprintf(stderr, "\n");
176 	fflush(stderr);
177 }
178 #endif
179 
180 static void dbgprint_sig(const char *name) {
181 #if DEBUG
182 	char buf[256];
183 	char *p = buf;
184 
185 	/* fprintf not used to be signal safe */
186 	p = sigstr_cat(p, "[");
187 	p = sigstr_itoa(p, getpid());
188 	p = sigstr_cat(p, "] ");
189 	p = sigstr_cat(p, name);
190 	p = sigstr_cat(p, "\n");
191 	write(STDERR_FILENO, buf, p - buf);
192 #endif
193 }
194 
195 #define SIGNAL(sig, handler) (signal_checked((sig), (handler), #sig, __FILE__, __FUNCTION__, __LINE__))
196 
197 static void signal_checked(int sig, void (* handler)(int), const char *signame,
198 	const char *file, const char *func, int line) {
199 	char buf[256];
200 	char *p = buf;
201 	struct sigaction sa = {
202 		.sa_handler = handler,
203 	};
204 
205 	if (sigaction(sig, &sa, NULL) == 0) return;
206 
207 	/* efmt not used to be signal safe */
208 	p = sigstr_cat(p, "[");
209 	p = sigstr_cat(p, file);
210 	p = sigstr_cat(p, ":");
211 	p = sigstr_itoa(p, line);
212 	p = sigstr_cat(p, "] error: sigaction(");
213 	p = sigstr_cat(p, signame);
214 	p = sigstr_cat(p, ") failed in function ");
215 	p = sigstr_cat(p, func);
216 	p = sigstr_cat(p, ": ");
217 	p = sigstr_itoa(p, errno);
218 	p = sigstr_cat(p, "\n");
219 	write(STDERR_FILENO, buf, p - buf);
220 	errct++;
221 }
222 
223 static void server_sigusr1(int signo) {
224 	dbgprint_sig("SIGUSR1");
225 
226 	/* terminate on the first opportunity */
227 	server_done = 1;
228 
229 	/* in case signal is caught before a blocking operation,
230 	 * keep interrupting
231 	 */
232 	server_alarm(1);
233 }
234 
235 static void server_stop(pid_t pid) {
236 
237 	if (pid < 0) return;
238 
239 	dbgprintf("sending SIGUSR1 to child %d\n", (int) pid);
240 	if (kill(pid, SIGUSR1) != 0) efmt("kill failed");
241 }
242 
243 static void server_wait(pid_t pid) {
244 	int exitcode, status;
245 	pid_t r;
246 
247 	if (pid < 0) return;
248 
249 	dbgprintf("waiting for child %d\n", (int) pid);
250 	r = waitpid(pid, &status, 0);
251 	if (r != pid) {
252 		efmt("waitpid failed");
253 		return;
254 	}
255 
256 	if (WIFEXITED(status)) {
257 		exitcode = WEXITSTATUS(status);
258 		if (exitcode < 0) {
259 			efmt("negative exit code from child %d\n", (int) pid);
260 		} else {
261 			dbgprintf("child exited exitcode=%d\n", exitcode);
262 			errct += exitcode;
263 		}
264 	} else if (WIFSIGNALED(status)) {
265 		efmt("child killed by signal %d", WTERMSIG(status));
266 	} else {
267 		efmt("child has unexpected exit status 0x%x", status);
268 	}
269 }
270 
271 static void server_sigalrm(int signum) {
272 	server_alarm(1);
273 }
274 
275 static void server_alarm(int seconds) {
276 	SIGNAL(SIGALRM, server_sigalrm);
277 	alarm(seconds);
278 }
279 
280 static void server_no_alarm(void) {
281 	int errno_old = errno;
282 	alarm(0);
283 	SIGNAL(SIGALRM, SIG_DFL);
284 	errno = errno_old;
285 }
286 
287 static int server_rw(int fd, int is_write, int *success) {
288 	char buf[4096];
289 	ssize_t r;
290 
291 	/* return 0 means close connection, *success=0 means stop server */
292 
293 	if (is_write) {
294 		/* ignore SIGPIPE */
295 		SIGNAL(SIGPIPE, SIG_IGN);
296 
297 		/* initialize buffer */
298 		memset(buf, -1, sizeof(buf));
299 	}
300 
301 	/* don't block for more than 1s */
302 	server_alarm(1);
303 
304 	/* perform read or write operation */
305 	dbgprintf("server_rw waiting is_write=%d\n", is_write);
306 	r = is_write ? write(fd, buf, sizeof(buf)) : read(fd, buf, sizeof(buf));
307 
308 	/* stop alarm (preserves errno) */
309 	server_no_alarm();
310 
311 	/* handle read/write result */
312 	if (r >= 0) {
313 		dbgprintf("server_rw done\n");
314 		*success = 1;
315 		return r > 0;
316 	}
317 
318 	switch (errno) {
319 	case EINTR:
320 		dbgprintf("server_rw interrupted\n");
321 		*success = 1;
322 		return 0;
323 	case ECONNRESET:
324 		dbgprintf("server_rw connection reset\n");
325 		*success = 1;
326 		return 0;
327 	case EPIPE:
328 		if (is_write) {
329 			dbgprintf("server_rw EPIPE\n");
330 			*success = 1;
331 			return 0;
332 		}
333 		/* fall through */
334 	default:
335 		efmt("%s failed", is_write ? "write" : "read");
336 		*success = 0;
337 		return 0;
338 	}
339 }
340 
341 static int server_select(int fd, int is_rw, int *success,
342 	enum server_action *actionnext) {
343 	int r;
344 	fd_set readfds, writefds;
345 	struct timeval timeout = { .tv_sec = 1, .tv_usec = 0 };
346 
347 	/* return 0 means close connection, *success=0 means stop server */
348 
349 	/* prepare fd sets */
350 	FD_ZERO(&readfds);
351 	FD_SET(fd, &readfds);
352 	FD_ZERO(&writefds);
353 	if (is_rw) FD_SET(fd, &writefds);
354 
355 	/* perform select */
356 	errno = 0;
357 	dbgprintf("server_select waiting\n");
358 	r = select(fd + 1, &readfds, &writefds, NULL, &timeout);
359 
360 	/* handle result */
361 	if (r < 0) {
362 		switch (errno) {
363 		case EINTR:
364 			dbgprintf("server_select interrupted\n");
365 			*success = 1;
366 			return 0;
367 		default:
368 			efmt("select failed");
369 			*success = 0;
370 			return 0;
371 		}
372 	}
373 	if (r == 0) {
374 		dbgprintf("server_select nothing available\n");
375 		*success = 1;
376 		return 0;
377 	}
378 
379 	if (FD_ISSET(fd, &readfds)) {
380 		dbgprintf("server_select read available\n");
381 		*actionnext = sa_read;
382 		*success = 1;
383 		return 1;
384 	} else if (FD_ISSET(fd, &writefds)) {
385 		dbgprintf("server_select write available\n");
386 		*actionnext = sa_write;
387 		*success = 1;
388 		return 1;
389 	}
390 
391 	*success = 0;
392 	efmt("select did not set fd");
393 	return 0;
394 }
395 
396 static int server_accept(int servfd, int type, enum server_action action) {
397 	enum server_action actionnext;
398 	struct sockaddr addr;
399 	socklen_t addrsize;
400 	int connfd;
401 	int success = 0;
402 
403 	/* if connection-oriented, accept a conmection */
404 	if (type == SOCK_DGRAM) {
405 		connfd = servfd;
406 	} else {
407 		dbgprintf("server_accept waiting for connection\n");
408 		addrsize = sizeof(addr);
409 		connfd = accept(servfd, &addr, &addrsize);
410 		if (connfd < 0) {
411 			switch (errno) {
412 			case EINTR:
413 				dbgprintf("server_accept interrupted\n");
414 				return 1;
415 			default:
416 				efmt("cannot accept connection");
417 				return 0;
418 			}
419 		}
420 		dbgprintf("server_accept new connection\n");
421 	}
422 
423 	/* perform requested action while the connection is open */
424 	actionnext = action;
425 	while (!server_done) {
426 		switch (actionnext) {
427 		case sa_close:
428 			success = 1;
429 			goto cleanup;
430 		case sa_read:
431 			if (!server_rw(connfd, 0, &success)) goto cleanup;
432 			actionnext = action;
433 			break;
434 		case sa_selectr:
435 		case sa_selectrw:
436 			if (!server_select(connfd, actionnext == sa_selectrw,
437 				&success, &actionnext)) {
438 				goto cleanup;
439 			}
440 			break;
441 		case sa_write:
442 			if (!server_rw(connfd, 1, &success)) goto cleanup;
443 			actionnext = action;
444 			break;
445 		default:
446 			efmt("bad server action");
447 			success = 0;
448 			goto cleanup;
449 		}
450 	}
451 
452 	/* socket connection socket */
453 cleanup:
454 	dbgprintf("server_accept done success=%d\n", success);
455 	if (connfd != servfd) CLOSE(connfd);
456 	return success;
457 }
458 
459 static pid_t server_start(int type, int port, enum server_action action) {
460 	struct sockaddr_in addr = {
461 		.sin_family = AF_INET,
462 		.sin_port = htons(port),
463 		.sin_addr = { htonl(INADDR_ANY) },
464 	};
465 	int fd, on;
466 	pid_t pid = -1;
467 
468 	dbgprintf("server_start port %d\n", port);
469 
470 	/* create socket */
471 	fd = socket(AF_INET, type, 0);
472 	if (fd < 0) {
473 		efmt("cannot create socket");
474 		goto cleanup;
475 	}
476 
477 	on = 1;
478 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
479 		efmt("cannot set SO_REUSEADDR option on socket");
480 		goto cleanup;
481 	}
482 
483 	/* bind socket */
484 	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) {
485 		efmt("cannot bind socket");
486 		goto cleanup;
487 	}
488 
489 	/* make it a server socket if needed */
490 	if (type != SOCK_DGRAM) {
491 		if (listen(fd, 5) != 0) {
492 			efmt("cannot listen on socket");
493 			goto cleanup;
494 		}
495 	}
496 
497 	/* intercept SIGUSR1 in case parent wants the server to stop */
498 	SIGNAL(SIGUSR1, server_sigusr1);
499 
500 	/* fork; parent continues, child becomes server */
501 	pid = fork();
502 	if (pid < 0) {
503 		efmt("cannot create socket");
504 		goto cleanup;
505 	}
506 	if (pid) goto cleanup;
507 
508 	/* server loop */
509 	dbgprintf("server_start child\n");
510 	while (!server_done && server_accept(fd, type, action)) {}
511 	dbgprintf("server_start child returns\n");
512 
513 	CLOSE(fd);
514 	exit(errct);
515 
516 cleanup:
517 	dbgprintf("server_start parent returns pid=%d\n", (int) pid);
518 	if (fd >= 0) CLOSE(fd);
519 	return pid;
520 }
521 
522 static ssize_t send_packet_raw(int fd, const void *buf, size_t size) {
523 	struct sockaddr_in sin;
524 
525 	memset(&sin, 0, sizeof(sin));
526 	sin.sin_family = AF_INET;
527 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
528 
529 	return sendto(fd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));
530 }
531 
532 enum settings_ip {
533 	si_bad_version   = (1 <<  0),
534 	si_bad_ihl_small = (1 <<  1),
535 	si_bad_ihl_big   = (1 <<  2),
536 	si_bad_len_small = (1 <<  3),
537 	si_bad_len_big   = (1 <<  4),
538 	si_bad_len_huge  = (1 <<  5),
539 	si_bad_cs        = (1 <<  6),
540 	si_zero_cs       = (1 <<  7),
541 
542 	si_flag_evil     = (1 <<  8),
543 	si_flag_df       = (1 <<  9),
544 	si_flag_mf       = (1 << 10),
545 
546 	si_opt_end       = (1 << 11),
547 	si_opt_topsec    = (1 << 12),
548 	si_opt_nop       = (1 << 13),
549 	si_opt_badopt    = (1 << 14),
550 	si_opt_badpad    = (1 << 15),
551 };
552 
553 enum settings_udp {
554 	su_bad_len_small = (1 <<  0),
555 	su_bad_len_big   = (1 <<  1),
556 	su_bad_len_huge  = (1 <<  2),
557 	su_bad_cs        = (1 <<  3),
558 	su_zero_cs       = (1 <<  4),
559 };
560 
561 enum fragmode_ip {
562 	fi_as_needed,
563 	fi_one,
564 	fi_two,
565 	fi_frag_tiny,
566 	fi_frag_overlap,
567 	fi_frag_first,
568 	fi_frag_last,
569 	fi_frag_repeat,
570 	fi_fo_max,
571 };
572 
573 static uint16_t checksum_ip(const void *header, size_t headersize) {
574 	const uint16_t *p = header;
575 	uint32_t sum = 0;
576 
577 	while (headersize > 0) {
578 		assert(headersize >= sizeof(*p));
579 		sum += ntohs(*p);
580 		headersize -= sizeof(*p);
581 		p++;
582 	}
583 	sum += sum >> 16;
584 	return htons(~sum);
585 }
586 
587 static void send_packet_ip_base(
588 	int fd,
589 	enum settings_ip ipsettings,
590 	uint8_t  tos,
591 	uint16_t id,
592 	uint16_t fo,
593 	uint8_t  ttl,
594 	uint8_t  prot,
595 	uint32_t srcip,
596 	uint32_t dstip,
597 	const void *payload,
598 	size_t payloadsize) {
599 	uint8_t ver = (ipsettings & si_bad_version) ? 3 : 4;
600 	uint8_t ihl, ihl_fuzzed;
601 	uint16_t fl = ((ipsettings & si_flag_evil) ? IP_FLAG_EVIL : 0) |
602 	              ((ipsettings & si_flag_df)   ? IP_FLAG_DF   : 0) |
603 	              ((ipsettings & si_flag_mf)   ? IP_FLAG_MF   : 0);
604 	uint16_t len;
605 	int optlen;
606 	struct header_ip header = {
607 		.tos     = tos,
608 		.id      = htons(id),
609 		.fl_fo   = (fl << 13) | fo, /* no htons(), lwip swaps this */
610 		.ttl     = ttl,
611 		.prot    = prot,
612 		.cs      = 0,
613 		.src     = htonl(srcip),
614 		.dst     = htonl(dstip),
615 	};
616 	char packet[6536];
617 	size_t packetsize;
618 	ssize_t r;
619 
620 	dbgprintf("sending IP packet src=%d.%d.%d.%d dst=%d.%d.%d.%d "
621 		"payloadsize=%zu id=0x%.4x fragoff=%d%s\n",
622 		(uint8_t) (srcip >> 24), (uint8_t) (srcip >> 16),
623 		(uint8_t) (srcip >> 8), (uint8_t) (srcip >> 0),
624 		(uint8_t) (dstip >> 24), (uint8_t) (dstip >> 16),
625 		(uint8_t) (dstip >> 8), (uint8_t) (dstip >> 0),
626 		payloadsize, id, fo, (ipsettings & si_flag_mf) ? " (MF)" : "");
627 
628 	optlen = 0;
629 	if (ipsettings & si_opt_badpad) memset(header.opt, -1, sizeof(header.opt));
630 	if (ipsettings & si_opt_nop) header.opt[optlen++] = 0x01;
631 	if (ipsettings & si_opt_topsec) {
632 		header.opt[optlen++] = 0x82;
633 		header.opt[optlen++] = 0x0b;
634 		header.opt[optlen++] = 0x6b; /* S: top secret */
635 		header.opt[optlen++] = 0xc5; /* S: top secret */
636 		header.opt[optlen++] = 0x00; /* C */
637 		header.opt[optlen++] = 0x00; /* C */
638 		header.opt[optlen++] = 'A'; /* H */
639 		header.opt[optlen++] = 'B'; /* H */
640 		header.opt[optlen++] = 'C'; /* TCC */
641 		header.opt[optlen++] = 'D'; /* TCC */
642 		header.opt[optlen++] = 'E'; /* TCC */
643 	}
644 	if (ipsettings & si_opt_badopt) header.opt[optlen++] = 0xff;
645 	if (ipsettings & si_opt_end) header.opt[optlen++] = 0x00;
646 	assert(optlen <= sizeof(header.opt));
647 
648 	ihl = ihl_fuzzed = (20 + optlen + 3) / 4;
649 	if (ipsettings & si_bad_ihl_small) ihl_fuzzed = 4;
650 	if (ipsettings & si_bad_ihl_big) ihl_fuzzed = 15;
651 	header.ver_ihl = (ver << 4) | ihl_fuzzed;
652 
653 	len = ihl * 4 + payloadsize;
654 	if (ipsettings & si_bad_len_small) len = ihl * 4 - 1;
655 	if (ipsettings & si_bad_len_big) len += 1;
656 	if (ipsettings & si_bad_len_huge) len = 0xffff;
657 	header.len = len; /* no htons(), lwip swaps this */
658 
659 	packetsize = ihl * 4 + payloadsize;
660 	if (packetsize > sizeof(packet)) {
661 		payloadsize = sizeof(packet) - ihl * 4;
662 		packetsize = sizeof(packet);
663 	}
664 
665 	header.cs = checksum_ip(&header, ihl * 4);
666 	if (ipsettings & si_zero_cs) header.cs = 0;
667 	if (ipsettings & si_bad_cs) header.cs += 1;
668 
669 	memset(packet, 0, sizeof(packet));
670 	memcpy(packet, &header, ihl * 4);
671 	memcpy(packet + ihl * 4, payload, payloadsize);
672 
673 	errno = 0;
674 	r = send_packet_raw(fd, packet, packetsize);
675 	if (r == -1 && errno == EPACKSIZE &&
676 		(packetsize < 60 || packetsize > 1514)) {
677 		return;
678 	}
679 	if (r != packetsize) {
680 		efmt("write to network interface failed");
681 	}
682 }
683 
684 static void send_packet_ip(
685 	int fd,
686 	enum settings_ip ipsettings,
687 	uint8_t tos,
688 	uint16_t id,
689 	uint8_t ttl,
690 	uint8_t prot,
691 	uint32_t srcip,
692 	uint32_t dstip,
693 	enum fragmode_ip fragmode,
694 	const void *payload,
695 	size_t payloadsize) {
696 	enum settings_ip flags;
697 	size_t fragcount = 1;
698 	size_t fragsize, fragsizecur;
699 	size_t fragstart = 0;
700 	size_t fragstep;
701 
702 	switch (fragmode) {
703 	case fi_as_needed:
704 		fragsize = fragstep = 1500;
705 		fragcount = (payloadsize + fragsize - 1) / fragsize;
706 		break;
707 	case fi_one:
708 	case fi_fo_max:
709 		fragsize = fragstep = payloadsize;
710 		break;
711 	case fi_two:
712 		fragcount = 2;
713 		fragsize = fragstep = (payloadsize + 1) / 2;
714 		break;
715 	case fi_frag_tiny:
716 		fragcount = (payloadsize >= 100) ? 100 :
717 			(payloadsize < 1) ? 1 : payloadsize;
718 		fragsize = fragstep = (payloadsize + fragcount - 1) / fragcount;
719 		break;
720 	case fi_frag_overlap:
721 		fragcount = 2;
722 		fragsize = (payloadsize * 2 + 2) / 3;
723 		fragstep = (payloadsize + 1) / 2;
724 		break;
725 	case fi_frag_first:
726 		fragcount = 1;
727 		fragsize = fragstep = (payloadsize + 1) / 2;
728 		break;
729 	case fi_frag_last:
730 		fragcount = 1;
731 		fragsize = fragstep = (payloadsize + 1) / 2;
732 		break;
733 	case fi_frag_repeat:
734 		fragcount = 2;
735 		fragsize = payloadsize;
736 		fragstep = 0;
737 		break;
738 	default:
739 		abort();
740 	}
741 
742 	while (fragcount > 0) {
743 		if (fragstart >= payloadsize) {
744 			fragsizecur = 0;
745 		} else if (payloadsize - fragstart < fragsize) {
746 			fragsizecur = payloadsize - fragstart;
747 		} else {
748 			fragsizecur = fragsize;
749 		}
750 
751 		flags = 0;
752 		if (fragstart + fragsizecur < payloadsize) flags |= si_flag_mf;
753 		send_packet_ip_base(
754 			fd,
755 			ipsettings | flags,
756 			tos,
757 			id,
758 			(fragmode == fi_fo_max) ? 0x1fff : fragstart,
759 			ttl,
760 			prot,
761 			srcip,
762 			dstip,
763 			(uint8_t *) payload + fragstart,
764 			fragsizecur);
765 
766 		fragcount--;
767 		fragstart += fragstep;
768 	}
769 }
770 
771 static uint32_t checksum_udp_sum(const void *buf, size_t size) {
772 	const uint16_t *p = buf;
773 	uint32_t sum = 0;
774 
775 	while (size > 0) {
776 		assert(size >= sizeof(*p));
777 		sum += ntohs(*p);
778 		size -= sizeof(*p);
779 		p++;
780 	}
781 	return sum;
782 }
783 
784 static uint16_t checksum_udp(
785 	uint32_t srcip,
786 	uint32_t dstip,
787 	uint8_t prot,
788 	const void *packet,
789 	size_t packetsize) {
790 	uint32_t sum = 0;
791 	struct header_udp_pseudo header = {
792 		.src = htonl(srcip),
793 		.dst = htonl(dstip),
794 		.zero = 0,
795 		.prot = prot,
796 		.len = htons(packetsize),
797 	};
798 
799 	sum = checksum_udp_sum(&header, sizeof(header)) +
800 		checksum_udp_sum(packet, packetsize + packetsize % 2);
801 	sum += sum >> 16;
802 	return ntohs(~sum);
803 }
804 
805 static void send_packet_udp(
806 	int fd,
807 	enum settings_ip ipsettings,
808 	uint8_t tos,
809 	uint16_t id,
810 	uint8_t ttl,
811 	uint8_t prot,
812 	uint32_t srcip,
813 	uint32_t dstip,
814 	enum fragmode_ip fragmode,
815 	enum settings_udp udpsettings,
816 	uint16_t srcport,
817 	uint16_t dstport,
818 	const void *payload,
819 	size_t payloadsize) {
820 	uint16_t len;
821 	struct header_udp header = {
822 		.src = htons(srcport),
823 		.dst = htons(dstport),
824 		.cs = 0,
825 	};
826 	char packet[65536];
827 	size_t packetsize;
828 
829 	dbgprintf("sending UDP packet srcport=%d dstport=%d payloadsize=%zu\n",
830 		srcport, dstport, payloadsize);
831 
832 	len = sizeof(struct header_udp) + payloadsize;
833 	if (udpsettings & su_bad_len_small) len = sizeof(struct header_udp) - 1;
834 	if (udpsettings & su_bad_len_big) len += 1;
835 	if (udpsettings & su_bad_len_huge) len = 65535 - sizeof(struct header_ip);
836 	header.len = htons(len);
837 
838 	packetsize = sizeof(header) + payloadsize;
839 	assert(packetsize <= sizeof(packet));
840 
841 	memcpy(packet, &header, sizeof(header));
842 	memcpy(packet + sizeof(header), payload, payloadsize);
843 	if (packetsize % 2) packet[packetsize] = 0;
844 
845 	header.cs = checksum_udp(srcip, dstip, prot, packet, packetsize);
846 	if (udpsettings & su_zero_cs) header.cs = 0;
847 	if (udpsettings & su_bad_cs) header.cs += 1;
848 
849 	memcpy(packet, &header, sizeof(header));
850 	send_packet_ip(
851 		fd,
852 		ipsettings,
853 		tos,
854 		id,
855 		ttl,
856 		prot,
857 		srcip,
858 		dstip,
859 		fragmode,
860 		packet,
861 		packetsize);
862 }
863 
864 struct send_packet_udp_simple_params {
865 	int fd;
866 	enum settings_ip ipsettings;
867 	uint8_t tos;
868 	uint16_t *id;
869 	uint8_t ttl;
870 	uint8_t prot;
871 	uint32_t srcip;
872 	uint32_t dstip;
873 	enum fragmode_ip fragmode;
874 	enum settings_udp udpsettings;
875 	uint16_t srcport;
876 	uint16_t dstport;
877 	size_t payloadsize;
878 };
879 
880 static void send_packet_udp_simple(
881 	const struct send_packet_udp_simple_params *params) {
882 	int i;
883 	char payload[65536];
884 
885 	assert(params->payloadsize <= sizeof(payload));
886 	for (i = 0; i < params->payloadsize; i++) {
887 		payload[i] = *params->id + i;
888 	}
889 
890 	send_packet_udp(
891 		params->fd,
892 		params->ipsettings,
893 		params->tos,
894 		*params->id,
895 		params->ttl,
896 		params->prot,
897 		params->srcip,
898 		params->dstip,
899 		params->fragmode,
900 		params->udpsettings,
901 		params->srcport,
902 		params->dstport,
903 		payload,
904 		params->payloadsize);
905 	*params->id += 5471;
906 }
907 
908 static void send_packets_ip_settings(
909 	const struct send_packet_udp_simple_params *paramsbase) {
910 	struct send_packet_udp_simple_params params;
911 	int i;
912 	enum settings_ip ipsettings[] = {
913 		0,
914 		si_bad_version,
915 		si_bad_ihl_small,
916 		si_bad_ihl_big,
917 		si_bad_len_small,
918 		si_bad_len_big,
919 		si_bad_len_huge,
920 		si_bad_cs,
921 		si_zero_cs,
922 		si_flag_evil,
923 		si_flag_df,
924 		si_flag_mf,
925 		si_opt_end,
926 		si_opt_topsec,
927 		si_opt_nop,
928 		si_opt_badopt,
929 		si_opt_nop | si_opt_end | si_opt_badpad,
930 	};
931 	uint8_t ttls[] = { 0, 1, 127, 128, 255 };
932 
933 	/* various types of flags/options/corruptions */
934 	params = *paramsbase;
935 	for (i = 0; i < 17; i++) {
936 		params.ipsettings = ipsettings[i];
937 		send_packet_udp_simple(&params);
938 	}
939 
940 	/* various TTL settings */
941 	params = *paramsbase;
942 	for (i = 0; i < 5; i++) {
943 		params.ttl = ttls[i];
944 		send_packet_udp_simple(&params);
945 	}
946 }
947 
948 static void send_packets_ip(int fd) {
949 	enum fragmode_ip fragmode;
950 	int i, j;
951 	uint16_t id = 0;
952 	struct send_packet_udp_simple_params params;
953 	const struct send_packet_udp_simple_params paramsbase = {
954 		.fd            = fd,
955 		.ipsettings    = 0,
956 		.tos           = 0,
957 		.id            = &id,
958 		.ttl           = 10,
959 		.prot          = IP_PROT_UDP,
960 		.srcip         = addrsrc,
961 		.dstip         = addrdst,
962 		.fragmode      = fi_as_needed,
963 		.udpsettings   = 0,
964 		.srcport       = PORT_BASE + 0,
965 		.dstport       = PORT_BASE + 1,
966 		.payloadsize   = 1234,
967 	};
968 
969 	/* send packets with various payload sizes and corruptions */
970 	params = paramsbase;
971 	for (i = 0; i < PAYLOADSIZE_COUNT; i++) {
972 		params.payloadsize = payloadsizes[i];
973 		send_packets_ip_settings(&params);
974 	}
975 
976 	/* send packets with various addresses and corruptions */
977 	params = paramsbase;
978 	for (i = 0; i < __arraycount(addrs); i++) {
979 	for (j = 0; j < __arraycount(addrs); j++) {
980 		params.srcip = addrs[i];
981 		params.dstip = addrs[j];
982 		send_packets_ip_settings(&params);
983 	}
984 	}
985 
986 	/* send valid packets with various fragmentation settings */
987 	params = paramsbase;
988 	for (i = 0; i < PAYLOADSIZE_COUNT; i++) {
989 	for (fragmode = fi_as_needed; fragmode <= fi_fo_max; fragmode++) {
990 		params.payloadsize = payloadsizes[i];
991 		params.fragmode = fragmode;
992 		send_packet_udp_simple(&params);
993 	}
994 	}
995 
996 	/* send a packet for each protocol */
997 	params = paramsbase;
998 	for (i = 0; i < 256; i++) {
999 		params.prot = i;
1000 		send_packet_udp_simple(&params);
1001 	}
1002 
1003 	/* send a packet for each tos */
1004 	params = paramsbase;
1005 	for (i = 0; i < 256; i++) {
1006 		params.tos = i;
1007 		send_packet_udp_simple(&params);
1008 	}
1009 }
1010 
1011 static void send_packets_udp(int fd) {
1012 	int i, j, k;
1013 	uint16_t id = 0;
1014 	struct send_packet_udp_simple_params params;
1015 	const struct send_packet_udp_simple_params paramsbase = {
1016 		.fd            = fd,
1017 		.ipsettings    = 0,
1018 		.tos           = 0,
1019 		.id            = &id,
1020 		.ttl           = 10,
1021 		.prot          = IP_PROT_UDP,
1022 		.srcip         = addrsrc,
1023 		.dstip         = addrdst,
1024 		.fragmode      = fi_as_needed,
1025 		.udpsettings   = 0,
1026 		.srcport       = PORT_BASE + 0,
1027 		.dstport       = PORT_BASE + 1,
1028 		.payloadsize   = 1234,
1029 	};
1030 	uint16_t ports[] = {
1031 		0,
1032 		PORT_BASE + 0,
1033 		PORT_BASE + 1,
1034 		32767,
1035 		65535,
1036 	};
1037 	enum settings_udp udpsettings[] = {
1038 		0,
1039 		su_bad_len_small,
1040 		su_bad_len_big,
1041 		su_bad_len_huge,
1042 		su_bad_cs,
1043 		su_zero_cs,
1044 	};
1045 
1046 	/* send packets with various corruptions */
1047 	params = paramsbase;
1048 	for (i = 0; i < 6; i++) {
1049 		params.udpsettings = udpsettings[i];
1050 		send_packet_udp_simple(&params);
1051 	}
1052 
1053 	/* send packets with various addresses and ports */
1054 	params = paramsbase;
1055 	for (i = 0; i < __arraycount(addrs); i++) {
1056 	for (j = 0; j < __arraycount(addrs); j++) {
1057 	for (k = 0; k < 5; k++) {
1058 		params.srcip = addrs[i];
1059 		params.dstip = addrs[j];
1060 		params.dstport = ports[k];
1061 		send_packet_udp_simple(&params);
1062 	}
1063 	}
1064 	}
1065 	params = paramsbase;
1066 	for (i = 0; i < __arraycount(addrs); i++) {
1067 	for (j = 0; j < 5; j++) {
1068 	for (k = 0; k < 5; k++) {
1069 		params.dstip = addrs[i];
1070 		params.srcport = ports[j];
1071 		params.dstport = ports[k];
1072 		send_packet_udp_simple(&params);
1073 	}
1074 	}
1075 	}
1076 }
1077 
1078 enum settings_tcp {
1079 	st_bad_doff_small  = (1 <<  0),
1080 	st_bad_doff_big    = (1 <<  1),
1081 	st_bad_doff_huge   = (1 <<  2),
1082 	st_bad_cs          = (1 <<  3),
1083 	st_zero_cs         = (1 <<  4),
1084 	st_opt_end         = (1 <<  5),
1085 	st_opt_nop         = (1 <<  6),
1086 	st_opt_mss_small   = (1 <<  7),
1087 	st_opt_mss_big     = (1 <<  8),
1088 	st_opt_mss_huge    = (1 <<  9),
1089 	st_opt_badpad      = (1 << 10),
1090 };
1091 
1092 static void send_packet_tcp(
1093 	int fd,
1094 	enum settings_ip ipsettings,
1095 	uint8_t tos,
1096 	uint16_t id,
1097 	uint8_t ttl,
1098 	uint8_t prot,
1099 	uint32_t srcip,
1100 	uint32_t dstip,
1101 	enum fragmode_ip fragmode,
1102 	enum settings_tcp tcpsettings,
1103 	uint16_t srcport,
1104 	uint16_t dstport,
1105 	uint32_t seq,
1106 	uint32_t ack,
1107 	uint8_t fl,
1108 	uint16_t win,
1109 	uint16_t uptr,
1110 	const void *payload,
1111 	size_t payloadsize) {
1112 	uint8_t doff, doff_fuzzed;
1113 	int optlen;
1114 	struct header_tcp header = {
1115 		.src  = htons(srcport),
1116 		.dst  = htons(dstport),
1117 		.seq  = htonl(seq),
1118 		.ack  = htonl(ack),
1119 		.fl   = fl,
1120 		.win  = htons(win),
1121 		.cs   = 0,
1122 		.uptr = htons(uptr),
1123 	};
1124 	char packet[65536];
1125 	size_t packetsize;
1126 
1127 	dbgprintf("sending TCP packet srcport=%d dstport=%d fl=%s%s%s%s%s%s "
1128 		"payloadsize=%zu\n", srcport, dstport,
1129 		(fl & TCP_FLAG_URG) ? "  URG" : "",
1130 		(fl & TCP_FLAG_ACK) ? "  ACK" : "",
1131 		(fl & TCP_FLAG_PSH) ? "  PSH" : "",
1132 		(fl & TCP_FLAG_RST) ? "  RST" : "",
1133 		(fl & TCP_FLAG_SYN) ? "  SYN" : "",
1134 		(fl & TCP_FLAG_FIN) ? "  FIN" : "",
1135 		payloadsize);
1136 
1137 	optlen = 0;
1138 	if (tcpsettings & st_opt_badpad) memset(header.opt, -1, sizeof(header.opt));
1139 	if (tcpsettings & st_opt_nop) header.opt[optlen++] = 0x01;
1140 	if (tcpsettings & st_opt_mss_small) {
1141 		header.opt[optlen++] = 0x02;
1142 		header.opt[optlen++] = 0x04;
1143 		header.opt[optlen++] = 0x00;
1144 		header.opt[optlen++] = 0x00;
1145 	}
1146 	if (tcpsettings & st_opt_mss_big) {
1147 		header.opt[optlen++] = 0x02;
1148 		header.opt[optlen++] = 0x04;
1149 		header.opt[optlen++] = 0x10;
1150 		header.opt[optlen++] = 0x00;
1151 	}
1152 	if (tcpsettings & st_opt_mss_huge) {
1153 		header.opt[optlen++] = 0x02;
1154 		header.opt[optlen++] = 0x04;
1155 		header.opt[optlen++] = 0xff;
1156 		header.opt[optlen++] = 0xff;
1157 	}
1158 	if (tcpsettings & st_opt_end) header.opt[optlen++] = 0x00;
1159 
1160 	doff = doff_fuzzed = (20 + optlen + 3) / 4;
1161 	if (tcpsettings & su_bad_len_small) doff_fuzzed -= 1;
1162 	if (tcpsettings & su_bad_len_big) doff_fuzzed += 1;
1163 	if (tcpsettings & su_bad_len_huge) doff_fuzzed = 15;
1164 	header.doff = doff_fuzzed << 4;
1165 
1166 	packetsize = doff * 4 + payloadsize;
1167 	assert(packetsize <= sizeof(packet));
1168 
1169 	memcpy(packet, &header, sizeof(header));
1170 	memcpy(packet + sizeof(header), payload, payloadsize);
1171 	if (packetsize % 2) packet[packetsize] = 0;
1172 
1173 	header.cs = checksum_udp(srcip, dstip, prot, packet, packetsize);
1174 	if (tcpsettings & su_zero_cs) header.cs = 0;
1175 	if (tcpsettings & su_bad_cs) header.cs += 1;
1176 
1177 	memcpy(packet, &header, sizeof(header));
1178 	send_packet_ip(
1179 		fd,
1180 		ipsettings,
1181 		tos,
1182 		id,
1183 		ttl,
1184 		prot,
1185 		srcip,
1186 		dstip,
1187 		fragmode,
1188 		packet,
1189 		packetsize);
1190 }
1191 
1192 struct send_packet_tcp_simple_params {
1193 	int fd;
1194 	enum settings_ip ipsettings;
1195 	uint8_t tos;
1196 	uint16_t *id;
1197 	uint8_t ttl;
1198 	uint8_t prot;
1199 	uint32_t srcip;
1200 	uint32_t dstip;
1201 	enum fragmode_ip fragmode;
1202 	enum settings_tcp tcpsettings;
1203 	uint16_t srcport;
1204 	uint16_t dstport;
1205 	uint32_t seq;
1206 	uint32_t ack;
1207 	uint8_t fl;
1208 	uint16_t win;
1209 	uint16_t uptr;
1210 	size_t payloadsize;
1211 };
1212 
1213 static void send_packet_tcp_simple(
1214 	const struct send_packet_tcp_simple_params *params) {
1215 	int i;
1216 	char payload[65536];
1217 
1218 	if (!params->srcip || !params->dstip) return; /* crashes QEMU */
1219 
1220 	assert(params->payloadsize <= sizeof(payload));
1221 	for (i = 0; i < params->payloadsize; i++) {
1222 		payload[i] = *params->id + i;
1223 	}
1224 	send_packet_tcp(
1225 		params->fd,
1226 		params->ipsettings,
1227 		params->tos,
1228 		*params->id,
1229 		params->ttl,
1230 		params->prot,
1231 		params->srcip,
1232 		params->dstip,
1233 		params->fragmode,
1234 		params->tcpsettings,
1235 		params->srcport,
1236 		params->dstport,
1237 		params->seq,
1238 		params->ack,
1239 		params->fl,
1240 		params->win,
1241 		params->uptr,
1242 		payload,
1243 		params->payloadsize);
1244 	*params->id += 5471;
1245 }
1246 
1247 static void send_packets_tcp(int fd) {
1248 	int i, j, k;
1249 	uint16_t id = 0;
1250 	const struct send_packet_tcp_simple_params paramsbase = {
1251 		.fd          = fd,
1252 		.ipsettings  = 0,
1253 		.tos         = 0,
1254 		.id          = &id,
1255 		.ttl         = 10,
1256 		.prot        = IP_PROT_TCP,
1257 		.srcip       = addrsrc,
1258 		.dstip       = addrdst,
1259 		.fragmode    = fi_as_needed,
1260 		.tcpsettings = 0,
1261 		.srcport     = PORT_BASE + 0,
1262 		.dstport     = PORT_BASE + 1,
1263 		.seq         = 0x12345678,
1264 		.ack         = 0x87654321,
1265 		.fl          = TCP_FLAG_SYN,
1266 		.win         = 4096,
1267 		.uptr        = 0,
1268 		.payloadsize = 1234,
1269 	};
1270 	uint16_t payloadsizes[] = {
1271 		0,
1272 		1,
1273 		999,
1274 		1500,
1275 		1600,
1276 		9999,
1277 	};
1278 	uint16_t ports[] = {
1279 		0,
1280 		PORT_BASE + 0,
1281 		PORT_BASE + 1,
1282 		PORT_BASE + 2,
1283 		PORT_BASE + 3,
1284 		32767,
1285 		65535,
1286 	};
1287 	enum settings_tcp tcpsettings[] = {
1288 		0,
1289 		st_bad_doff_small,
1290 		st_bad_doff_big,
1291 		st_bad_doff_huge,
1292 		st_bad_cs,
1293 		st_zero_cs,
1294 		st_opt_end,
1295 		st_opt_nop,
1296 		st_opt_mss_small,
1297 		st_opt_mss_big,
1298 		st_opt_mss_huge,
1299 		st_opt_badpad,
1300 	};
1301 	struct send_packet_tcp_simple_params params;
1302 
1303 	/* send packets with various corruptions */
1304 	params = paramsbase;
1305 	for (i = 0; i < 12; i++) {
1306 		params.tcpsettings = tcpsettings[i];
1307 		send_packet_tcp_simple(&params);
1308 	}
1309 
1310 	/* send packets with various addresses and ports */
1311 	params = paramsbase;
1312 	for (i = 0; i < __arraycount(addrs); i++) {
1313 	for (j = 0; j < __arraycount(addrs); j++) {
1314 	for (k = 0; k < 7; k++) {
1315 		params.srcip = addrs[i];
1316 		params.dstip = addrs[j];
1317 		params.dstport = ports[k];
1318 		send_packet_tcp_simple(&params);
1319 	}
1320 	}
1321 	}
1322 	params = paramsbase;
1323 	for (i = 0; i < __arraycount(addrs); i++) {
1324 	for (j = 0; j < 7; j++) {
1325 	for (k = 0; k < 7; k++) {
1326 		params.dstip = addrs[i];
1327 		params.srcport = ports[j];
1328 		params.dstport = ports[k];
1329 		send_packet_tcp_simple(&params);
1330 	}
1331 	}
1332 	}
1333 
1334 	/* send packets with different sequence numbers */
1335 	params = paramsbase;
1336 	for (i = 0; i < 16; i++) {
1337 		params.seq = 0x1fffffff;
1338 		send_packet_tcp_simple(&params);
1339 	}
1340 
1341 	/* send packets with all combinations of flags */
1342 	params = paramsbase;
1343 	for (i = 0; i < 256; i++) {
1344 		params.fl = i;
1345 		send_packet_tcp_simple(&params);
1346 	}
1347 
1348 	/* send packets with different window sizes */
1349 	params = paramsbase;
1350 	for (i = 0; i < 6; i++) {
1351 		params.win = payloadsizes[i];
1352 		send_packet_tcp_simple(&params);
1353 	}
1354 
1355 	/* send packets with different payload sizes */
1356 	params = paramsbase;
1357 	for (i = 0; i < 6; i++) {
1358 		params.payloadsize = payloadsizes[i];
1359 		send_packet_tcp_simple(&params);
1360 	}
1361 }
1362 
1363 static void recv_packets_nb(int fd) {
1364 	char buf[4096];
1365 	int flags;
1366 	ssize_t r;
1367 
1368 	flags = fcntl(fd, F_GETFL);
1369 	if (flags < 0) {
1370 		efmt("fcntl(F_GETFL) failed");
1371 		return;
1372 	}
1373 
1374 	if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
1375 		efmt("fcntl(F_SETFL) failed");
1376 		return;
1377 	}
1378 
1379 	for (;;) {
1380 		errno = 0;
1381 		r = read(fd, buf, sizeof(buf));
1382 		if (r <= 0) {
1383 			if (errno != EAGAIN) efmt("nb read failed");
1384 			dbgprintf("no more packets to receive\n");
1385 			break;
1386 		}
1387 		dbgprintf("received packet of size %zd\n", r);
1388 	}
1389 
1390 	if (fcntl(fd, F_SETFL, flags) == -1) {
1391 		efmt("fcntl(F_SETFL) failed");
1392 		return;
1393 	}
1394 }
1395 
1396 static struct timeval gettimeofday_checked(void) {
1397 	struct timeval time = {};
1398 
1399 	if (gettimeofday(&time, NULL) != 0) {
1400 		efmt("gettimeofday failed");
1401 	}
1402 	return time;
1403 }
1404 
1405 static int timeval_cmp(const struct timeval *x, const struct timeval *y) {
1406 	if (x->tv_sec < y->tv_sec) return -1;
1407 	if (x->tv_sec > y->tv_sec) return 1;
1408 	if (x->tv_usec < y->tv_usec) return -1;
1409 	if (x->tv_usec > y->tv_usec) return 1;
1410 	return 0;
1411 }
1412 
1413 static struct timeval timeval_sub(struct timeval x, struct timeval y) {
1414 	struct timeval z;
1415 
1416 	/* no negative result allowed */
1417 	if (timeval_cmp(&x, &y) < 0) {
1418 		memset(&z, 0, sizeof(z));
1419 	} else {
1420 		/* no negative tv_usec allowed */
1421 		if (x.tv_usec < y.tv_usec) {
1422 			x.tv_sec -= 1;
1423 			x.tv_usec += 1000000;
1424 		}
1425 
1426 		/* perform subtraction */
1427 		z.tv_sec = x.tv_sec - y.tv_sec;
1428 		z.tv_usec = x.tv_usec - y.tv_usec;
1429 	}
1430 	return z;
1431 }
1432 
1433 static size_t recv_packet_select(
1434 	int fd,
1435 	void *buf,
1436 	size_t size,
1437 	const struct timeval *deadline) {
1438 	int nfds;
1439 	ssize_t r;
1440 	fd_set readfds;
1441 	struct timeval timeout = timeval_sub(*deadline, gettimeofday_checked());
1442 
1443 	FD_ZERO(&readfds);
1444 	FD_SET(fd, &readfds);
1445 	errno = 0;
1446 	nfds = select(fd + 1, &readfds, NULL, NULL, &timeout);
1447 	if (nfds < 0 || nfds > 1) {
1448 		efmt("select failed");
1449 		return 0;
1450 	}
1451 
1452 	if (nfds == 0) {
1453 		if (FD_ISSET(fd, &readfds)) efmt("select spuriously set fd");
1454 		dbgprintf("no more packets to receive\n");
1455 		return 0;
1456 	}
1457 
1458 	if (!FD_ISSET(fd, &readfds)) {
1459 		efmt("select did not set fd");
1460 		return 0;
1461 	}
1462 
1463 	r = read(fd, buf, size);
1464 	if (r <= 0) {
1465 		efmt("read failed");
1466 		return 0;
1467 	}
1468 	dbgprintf("received packet of size %zd\n", r);
1469 
1470 	return r;
1471 }
1472 
1473 static void recv_packets_select(int fd) {
1474 	char buf[4096];
1475 	struct timeval deadline = gettimeofday_checked();
1476 
1477 	deadline.tv_sec++;
1478 	while (recv_packet_select(fd, buf, sizeof(buf), &deadline)) { }
1479 }
1480 
1481 static int open_raw_socket(int broadcast) {
1482 	int fd, on;
1483 
1484 	fd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
1485 	if (fd < 0) efmt("cannot create raw socket");
1486 
1487 	on = 1;
1488 	if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) != 0)
1489 		efmt("ioctl(IP_HDRINCL) failed");
1490 
1491 	return fd;
1492 }
1493 
1494 static void do_packets(void) {
1495 	int fd;
1496 
1497 	/* test IP and UDP with broadcast */
1498 	fd = open_raw_socket(1 /*broadcast*/);
1499 	if (fd < 0) return;
1500 
1501 	send_packets_ip(fd);
1502 	send_packets_udp(fd);
1503 	recv_packets_nb(fd);
1504 
1505 	CLOSE(fd);
1506 
1507 	/* test TCP locally to avoid crashing QEMU */
1508 	fd = open_raw_socket(0 /*broadcast*/);
1509 	if (fd < 0) return;
1510 
1511 	send_packets_tcp(fd);
1512 	recv_packets_select(fd);
1513 
1514 	CLOSE(fd);
1515 }
1516 
1517 int main(int argc, char **argv)
1518 {
1519 	int i;
1520 	pid_t pids[PORT_COUNT];
1521 
1522 	start(83);
1523 
1524 	/* start servers so we have someone to talk to */
1525 	pids[0] = server_start(SOCK_STREAM, PORT_BASE + 0, sa_close);
1526 	pids[1] = server_start(SOCK_STREAM, PORT_BASE + 1, sa_read);
1527 	pids[2] = server_start(SOCK_STREAM, PORT_BASE + 2, sa_selectrw);
1528 	pids[3] = server_start(SOCK_STREAM, PORT_BASE + 3, sa_write);
1529 	pids[4] = server_start(SOCK_DGRAM,  PORT_BASE + 0, sa_read);
1530 	pids[5] = server_start(SOCK_DGRAM,  PORT_BASE + 1, sa_selectr);
1531 
1532 	/* send some bogus packets */
1533 	do_packets();
1534 
1535 	/* stop the servers */
1536 	for (i = 0; i < PORT_COUNT; i++) server_stop(pids[i]);
1537 	for (i = 0; i < PORT_COUNT; i++) server_wait(pids[i]);
1538 
1539 	quit();
1540 	return 0;
1541 }
1542