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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); 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