1 /* 2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 * OF SUCH DAMAGE. 26 * 27 * This file is part of the lwIP TCP/IP stack. 28 * 29 * Author: Erik Ekman <erik@kryo.se> 30 * Simon Goldschmidt <goldsimon@gmx.de> 31 * 32 */ 33 34 #include "fuzz_common.h" 35 36 #include "lwip/altcp_tcp.h" 37 #include "lwip/dns.h" 38 #include "lwip/init.h" 39 #include "lwip/netif.h" 40 #include "lwip/sys.h" 41 #include "lwip/timeouts.h" 42 #include "lwip/udp.h" 43 #include "netif/etharp.h" 44 #if LWIP_IPV6 45 #include "lwip/ethip6.h" 46 #include "lwip/nd6.h" 47 #endif 48 49 #include "lwip/apps/httpd.h" 50 #include "lwip/apps/snmp.h" 51 #include "lwip/apps/lwiperf.h" 52 #include "lwip/apps/mdns.h" 53 54 #include <string.h> 55 #include <stdio.h> 56 57 static u8_t pktbuf[200000]; 58 static const u8_t *remfuzz_ptr; /* remaining fuzz pointer */ 59 static size_t remfuzz_len; /* remaining fuzz length */ 60 61 #ifndef FUZZ_DEBUG 62 #define FUZZ_DEBUG LWIP_DBG_OFF 63 #endif 64 65 #ifdef LWIP_FUZZ_SYS_NOW 66 /* This offset should be added to the time 'sys_now()' returns */ 67 u32_t sys_now_offset; 68 #endif 69 70 /** Set this to 1 and define FUZZ_DUMP_PCAP_FILE to dump tx and rx packets into 71 * a pcap file. At the same time, packet info is written via LWIP_DEBUGF so 72 * packets can be matched to other events for debugging them. 73 */ 74 #ifndef FUZZ_DUMP_PCAP 75 #define FUZZ_DUMP_PCAP 0 76 #endif 77 78 #if FUZZ_DUMP_PCAP 79 const u8_t pcap_file_header[24] = { 80 0xd4, 0xc3, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00, 81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00 83 }; 84 85 static FILE* fpcap; 86 static u32_t pcap_packet; 87 88 static void pcap_dump_init(void) 89 { 90 fpcap = fopen(FUZZ_DUMP_PCAP_FILE, "wb"); 91 if (fpcap != NULL) { 92 /* write header */ 93 fwrite(pcap_file_header, 1, sizeof(pcap_file_header), fpcap); 94 } 95 } 96 97 /* This function might have to be called from LWIP_PLATFORM_ASSERT() 98 * in order to produce correct pcap results on crash. 99 * Define this global so that for a test, we can call this from anywhere... 100 */ 101 void pcap_dump_stop(void); 102 void pcap_dump_stop(void) 103 { 104 if (fpcap != NULL) { 105 fclose(fpcap); 106 fpcap = NULL; 107 } 108 } 109 110 static void pcap_dump_packet(struct pbuf *p, int is_tx) 111 { 112 if (fpcap != NULL) { 113 struct pbuf *q; 114 u32_t data; 115 pcap_packet++; 116 if (is_tx) { 117 LWIP_DEBUGF(FUZZ_DEBUG, ("> %d fuzz: netif: send %u bytes\n", pcap_packet, p->tot_len)); 118 } else { 119 LWIP_DEBUGF(FUZZ_DEBUG, ("< %d fuzz: RX packet of %u bytes\n", pcap_packet, p->tot_len)); 120 if (pcap_packet == 50 || pcap_packet == 33 || pcap_packet == 29) { 121 pcap_packet++; 122 pcap_packet--; 123 } 124 } 125 /* write packet header */ 126 fwrite(&pcap_packet, 1, sizeof(pcap_packet), fpcap); 127 data = 0; 128 fwrite(&data, 1, sizeof(data), fpcap); 129 data = p->tot_len; 130 fwrite(&data, 1, sizeof(data), fpcap); 131 fwrite(&data, 1, sizeof(data), fpcap); 132 /* write packet data */ 133 for(q = p; q != NULL; q = q->next) { 134 fwrite(q->payload, 1, q->len, fpcap); 135 } 136 } 137 } 138 139 static void pcap_dump_rx_packet(struct pbuf *p) 140 { 141 pcap_dump_packet(p, 0); 142 } 143 144 static void pcap_dump_tx_packet(struct pbuf *p) 145 { 146 pcap_dump_packet(p, 1); 147 } 148 #else /* FUZZ_DUMP_PCAP */ 149 #define pcap_dump_rx_packet(p) 150 #define pcap_dump_tx_packet(p) 151 #define pcap_dump_init() 152 #define pcap_dump_stop() 153 #endif /* FUZZ_DUMP_PCAP */ 154 155 /* no-op send function */ 156 static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) 157 { 158 pcap_dump_tx_packet(p); 159 LWIP_UNUSED_ARG(netif); 160 LWIP_UNUSED_ARG(p); 161 return ERR_OK; 162 } 163 164 static err_t testif_init(struct netif *netif) 165 { 166 netif->name[0] = 'f'; 167 netif->name[1] = 'z'; 168 netif->output = etharp_output; 169 netif->linkoutput = lwip_tx_func; 170 netif->mtu = 1500; 171 netif->hwaddr_len = 6; 172 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; 173 174 netif->hwaddr[0] = 0x00; 175 netif->hwaddr[1] = 0x23; 176 netif->hwaddr[2] = 0xC1; 177 netif->hwaddr[3] = 0xDE; 178 netif->hwaddr[4] = 0xD0; 179 netif->hwaddr[5] = 0x0D; 180 181 #if LWIP_IPV6 182 netif->output_ip6 = ethip6_output; 183 netif_create_ip6_linklocal_address(netif, 1); 184 netif->flags |= NETIF_FLAG_MLD6; 185 #endif 186 187 return ERR_OK; 188 } 189 190 static void input_pkt(struct netif *netif, const u8_t *data, size_t len) 191 { 192 struct pbuf *p, *q; 193 err_t err; 194 195 if (len > 0xFFFF) { 196 printf("pkt too big (%#zX bytes)\n", len); 197 return; 198 } 199 200 p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); 201 LWIP_ASSERT("alloc failed", p); 202 for(q = p; q != NULL; q = q->next) { 203 MEMCPY(q->payload, data, q->len); 204 data += q->len; 205 } 206 remfuzz_ptr += len; 207 remfuzz_len -= len; 208 pcap_dump_rx_packet(p); 209 err = netif->input(p, netif); 210 if (err != ERR_OK) { 211 pbuf_free(p); 212 } 213 } 214 215 static void input_pkts(enum lwip_fuzz_type type, struct netif *netif, const u8_t *data, size_t len) 216 { 217 remfuzz_ptr = data; 218 remfuzz_len = len; 219 220 if (type == LWIP_FUZZ_SINGLE) { 221 input_pkt(netif, data, len); 222 } else { 223 const u16_t max_packet_size = 1514; 224 const size_t minlen = sizeof(u16_t) + (type == LWIP_FUZZ_MULTIPACKET_TIME ? sizeof(u32_t) : 0); 225 226 while (remfuzz_len > minlen) { 227 u16_t frame_len; 228 #ifdef LWIP_FUZZ_SYS_NOW 229 u32_t external_delay = 0; 230 #endif 231 if (type == LWIP_FUZZ_MULTIPACKET_TIME) { 232 #ifdef LWIP_FUZZ_SYS_NOW 233 /* Extract external delay time from fuzz pool */ 234 memcpy(&external_delay, remfuzz_ptr, sizeof(u32_t)); 235 external_delay = ntohl(external_delay); 236 #endif 237 remfuzz_ptr += sizeof(u32_t); 238 remfuzz_len -= sizeof(u32_t); 239 } 240 memcpy(&frame_len, remfuzz_ptr, sizeof(u16_t)); 241 remfuzz_ptr += sizeof(u16_t); 242 remfuzz_len -= sizeof(u16_t); 243 frame_len = ntohs(frame_len) & 0x7FF; 244 frame_len = LWIP_MIN(frame_len, max_packet_size); 245 if (frame_len > remfuzz_len) { 246 frame_len = (u16_t)remfuzz_len; 247 } 248 if (frame_len != 0) { 249 if (type == LWIP_FUZZ_MULTIPACKET_TIME) { 250 #ifdef LWIP_FUZZ_SYS_NOW 251 /* Update total external delay time, and check timeouts */ 252 sys_now_offset += external_delay; 253 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: sys_now_offset += %u -> %u\n", external_delay, sys_now_offset)); 254 #endif 255 sys_check_timeouts(); 256 } 257 input_pkt(netif, remfuzz_ptr, frame_len); 258 /* Check timeouts again */ 259 sys_check_timeouts(); 260 } 261 } 262 } 263 } 264 265 #if LWIP_TCP 266 static struct altcp_pcb *tcp_client_pcb; /* a pcb for the TCP client */ 267 static struct altcp_pcb *tcp_server_pcb; /* a pcb for the TCP server */ 268 static u16_t tcp_remote_port; /* a TCP port number of the destionation */ 269 static u16_t tcp_local_port; /* a TCP port number of the local server */ 270 271 /** 272 * tcp_app_fuzz_input 273 * Input fuzz with a write function for TCP. 274 */ 275 static void 276 tcp_app_fuzz_input(struct altcp_pcb *pcb) 277 { 278 if (remfuzz_len > sizeof(u16_t)) { 279 /* 280 * (max IP packet size) - ((minimum IP header size) + (minimum TCP header size)) 281 * = 65535 - (20 + 20) 282 * = 65495 283 */ 284 const u16_t max_data_size = 65495; 285 u16_t data_len; 286 287 memcpy(&data_len, remfuzz_ptr, sizeof(u16_t)); 288 remfuzz_ptr += sizeof(u16_t); 289 remfuzz_len -= sizeof(u16_t); 290 data_len = ntohs(data_len); 291 data_len = LWIP_MIN(data_len, max_data_size); 292 if (data_len > remfuzz_len) { 293 data_len = (u16_t)remfuzz_len; 294 } 295 296 if (data_len != 0) { 297 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: tcp: write %u bytes\n", data_len)); 298 altcp_write(pcb, remfuzz_ptr, data_len, TCP_WRITE_FLAG_COPY); 299 altcp_output(pcb); 300 } else { 301 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: tcp: close\n")); 302 altcp_close(pcb); 303 } 304 305 remfuzz_ptr += data_len; 306 remfuzz_len -= data_len; 307 } 308 } 309 310 /** 311 * tcp_client_connected 312 * A connected callback function (for the TCP client) 313 */ 314 static err_t 315 tcp_client_connected(void *arg, struct altcp_pcb *pcb, err_t err) 316 { 317 LWIP_UNUSED_ARG(arg); 318 LWIP_UNUSED_ARG(err); 319 320 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: tcp: tcp_client_connected\n")); 321 tcp_app_fuzz_input(pcb); 322 323 return ERR_OK; 324 } 325 326 /** 327 * tcp_client_recv 328 * A recv callback function (for the TCP client) 329 */ 330 static err_t 331 tcp_client_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) 332 { 333 LWIP_UNUSED_ARG(arg); 334 LWIP_UNUSED_ARG(err); 335 336 if (p == NULL) { 337 altcp_close(pcb); 338 } else { 339 altcp_recved(pcb, p->tot_len); 340 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: tcp: tcp_client_recv: %d\n", p->tot_len)); 341 tcp_app_fuzz_input(pcb); 342 pbuf_free(p); 343 } 344 345 return ERR_OK; 346 } 347 348 /** 349 * tcp_client_sent 350 * A sent callback function (for the TCP client) 351 */ 352 static err_t 353 tcp_client_sent(void *arg, struct altcp_pcb *pcb, u16_t len) 354 { 355 LWIP_UNUSED_ARG(arg); 356 LWIP_UNUSED_ARG(pcb); 357 LWIP_UNUSED_ARG(len); 358 return ERR_OK; 359 } 360 361 /** 362 * tcp_client_poll 363 * A poll callback function (for the TCP client) 364 */ 365 static err_t 366 tcp_client_poll(void *arg, struct altcp_pcb *pcb) 367 { 368 LWIP_UNUSED_ARG(arg); 369 LWIP_UNUSED_ARG(pcb); 370 return ERR_OK; 371 } 372 373 /** 374 * tcp_client_err 375 * An err callback function (for the TCP client) 376 */ 377 static void 378 tcp_client_err(void *arg, err_t err) 379 { 380 LWIP_UNUSED_ARG(arg); 381 LWIP_UNUSED_ARG(err); 382 } 383 384 /** 385 * tcp_server_recv 386 * A recv callback function (for the TCP server) 387 */ 388 static err_t 389 tcp_server_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) 390 { 391 LWIP_UNUSED_ARG(arg); 392 LWIP_UNUSED_ARG(err); 393 394 if (p == NULL) { 395 altcp_close(pcb); 396 } else { 397 altcp_recved(pcb, p->tot_len); 398 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: tcp: tcp_server_recv: %d\n", p->tot_len)); 399 tcp_app_fuzz_input(pcb); 400 pbuf_free(p); 401 } 402 403 return ERR_OK; 404 } 405 406 /** 407 * tcp_server_sent 408 * A sent callback function (for the TCP server) 409 */ 410 static err_t 411 tcp_server_sent(void *arg, struct altcp_pcb *pcb, u16_t len) 412 { 413 LWIP_UNUSED_ARG(arg); 414 LWIP_UNUSED_ARG(pcb); 415 LWIP_UNUSED_ARG(len); 416 return ERR_OK; 417 } 418 419 /** 420 * tcp_server_poll 421 * A poll callback function (for the TCP server) 422 */ 423 static err_t 424 tcp_server_poll(void *arg, struct altcp_pcb *pcb) 425 { 426 LWIP_UNUSED_ARG(arg); 427 LWIP_UNUSED_ARG(pcb); 428 return ERR_OK; 429 } 430 431 /** 432 * tcp_server_err 433 * An err callbuck function (for the TCP server) 434 */ 435 static void 436 tcp_server_err(void *arg, err_t err) 437 { 438 LWIP_UNUSED_ARG(arg); 439 LWIP_UNUSED_ARG(err); 440 } 441 442 /** 443 * tcp_server_accept 444 * An accept callbuck function (for the TCP server) 445 */ 446 static err_t 447 tcp_server_accept(void *arg, struct altcp_pcb *pcb, err_t err) 448 { 449 LWIP_UNUSED_ARG(arg); 450 LWIP_UNUSED_ARG(err); 451 452 if ((err != ERR_OK) || (pcb == NULL)) { 453 return ERR_VAL; 454 } 455 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: accept from remote\n")); 456 457 altcp_setprio(pcb, TCP_PRIO_MIN); 458 459 altcp_recv(pcb, tcp_server_recv); 460 altcp_err(pcb, tcp_server_err); 461 altcp_poll(pcb, tcp_server_poll, 10); 462 altcp_sent(pcb, tcp_server_sent); 463 464 return ERR_OK; 465 } 466 #endif /* LWIP_TCP */ 467 468 #if LWIP_UDP 469 static struct udp_pcb *udp_client_pcb; /* a pcb for the UDP client */ 470 static struct udp_pcb *udp_server_pcb; /* a pcb for the UDP server */ 471 static u16_t udp_remote_port; /* a UDP port number of the destination */ 472 static u16_t udp_local_port; /* a UDP port number of the local server*/ 473 474 /** 475 * udp_app_fuzz_input 476 * Input fuzz with write functions for UDP. 477 */ 478 static void 479 udp_app_fuzz_input(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port) 480 { 481 if (remfuzz_len > sizeof(u16_t)) { 482 /* 483 * (max IP packet size) - ((minimum IP header size) - (minimum UDP header size)) 484 * = 65535 - (20 + 8) 485 * = 65507 486 */ 487 const u16_t max_data_size = 65507; 488 u16_t data_len; 489 490 memcpy(&data_len, remfuzz_ptr, sizeof(u16_t)); 491 remfuzz_ptr += sizeof(u16_t); 492 remfuzz_len -= sizeof(u16_t); 493 data_len = ntohs(data_len); 494 data_len = LWIP_MIN(data_len, max_data_size); 495 if (data_len > remfuzz_len) { 496 data_len = (u16_t)remfuzz_len; 497 } 498 499 LWIP_DEBUGF(FUZZ_DEBUG, ("fuzz: udp: send %u bytes\n", data_len)); 500 if (data_len != 0) { 501 struct pbuf *p, *q; 502 503 p = pbuf_alloc(PBUF_RAW, (u16_t)data_len, PBUF_POOL); 504 LWIP_ASSERT("alloc failed", p); 505 506 for (q = p; q != NULL; q = q->next) { 507 MEMCPY(q->payload, remfuzz_ptr, q->len); 508 remfuzz_ptr += q->len; 509 } 510 remfuzz_len -= data_len; 511 512 /* 513 * Trying input from ... 514 * 515 * client: 516 * The pcb has information about the destination. 517 * We use udp_send(). 518 * 519 * server: 520 * The pcb does NOT have infomation about the destionation. 521 * We use udp_sendto(). 522 */ 523 if (addr == NULL) { 524 udp_send(pcb, p); 525 } else { 526 udp_sendto(pcb, p, addr, port); 527 } 528 pbuf_free(p); 529 } 530 } 531 } 532 533 /** 534 * udp_client_recv 535 * A recv callback function (for the UDP client) 536 */ 537 static void 538 udp_client_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) 539 { 540 LWIP_UNUSED_ARG(arg); 541 LWIP_UNUSED_ARG(p); 542 LWIP_UNUSED_ARG(addr); 543 LWIP_UNUSED_ARG(port); 544 545 if (p == NULL) { 546 udp_disconnect(pcb); 547 } else { 548 /* 549 * We call the function with 2nd argument set to NULL 550 * to input fuzz from udp_send. 551 */ 552 udp_app_fuzz_input(pcb, NULL, port); 553 pbuf_free(p); 554 } 555 } 556 557 /** 558 * udp_server_recv 559 * A recv callback functyion (for the UDP server) 560 */ 561 static void 562 udp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) 563 { 564 LWIP_UNUSED_ARG(arg); 565 LWIP_UNUSED_ARG(p); 566 LWIP_UNUSED_ARG(addr); 567 LWIP_UNUSED_ARG(port); 568 569 if (p != NULL) { 570 udp_app_fuzz_input(pcb, addr, port); 571 pbuf_free(p); 572 } 573 } 574 #endif /* LWIP_UDP */ 575 576 int lwip_fuzztest(int argc, char** argv, enum lwip_fuzz_type type, u32_t test_apps) 577 { 578 struct netif net_test; 579 ip4_addr_t addr; 580 ip4_addr_t netmask; 581 ip4_addr_t gw; 582 size_t len; 583 err_t err; 584 ip_addr_t remote_addr; /* a IPv4 addr of the destination */ 585 struct eth_addr remote_mac = ETH_ADDR(0x28, 0x00, 0x00, 0x22, 0x2b, 0x38); /* a MAC addr of the destination */ 586 587 pcap_dump_init(); 588 lwip_init(); 589 590 IP4_ADDR(&addr, 172, 30, 115, 84); 591 IP4_ADDR(&netmask, 255, 255, 255, 0); 592 IP4_ADDR(&gw, 172, 30, 115, 1); 593 594 netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); 595 netif_set_up(&net_test); 596 netif_set_link_up(&net_test); 597 598 if (test_apps & LWIP_FUZZ_STATICARP) { 599 /* Add the ARP entry */ 600 IP_ADDR4(&remote_addr, 172, 30, 115, 37); 601 etharp_add_static_entry(&(remote_addr.u_addr.ip4), &remote_mac); 602 } 603 604 #if LWIP_IPV6 605 nd6_tmr(); /* tick nd to join multicast groups */ 606 #endif 607 dns_setserver(0, &net_test.gw); 608 609 if (test_apps & LWIP_FUZZ_DEFAULT) { 610 /* initialize apps */ 611 httpd_init(); 612 lwiperf_start_tcp_server_default(NULL, NULL); 613 mdns_resp_init(); 614 mdns_resp_add_netif(&net_test, "hostname"); 615 snmp_init(); 616 } 617 if (test_apps & LWIP_FUZZ_TCP_CLIENT) { 618 tcp_client_pcb = altcp_tcp_new_ip_type(IPADDR_TYPE_ANY); 619 LWIP_ASSERT("Error: altcp_new() failed", tcp_client_pcb != NULL); 620 tcp_remote_port = 80; 621 err = altcp_connect(tcp_client_pcb, &remote_addr, tcp_remote_port, tcp_client_connected); 622 LWIP_ASSERT("Error: altcp_connect() failed", err == ERR_OK); 623 altcp_recv(tcp_client_pcb, tcp_client_recv); 624 altcp_err(tcp_client_pcb, tcp_client_err); 625 altcp_poll(tcp_client_pcb, tcp_client_poll, 10); 626 altcp_sent(tcp_client_pcb, tcp_client_sent); 627 } 628 if (test_apps & LWIP_FUZZ_TCP_SERVER) { 629 tcp_server_pcb = altcp_tcp_new_ip_type(IPADDR_TYPE_ANY); 630 LWIP_ASSERT("Error: altcp_new() failed", tcp_server_pcb != NULL); 631 altcp_setprio(tcp_server_pcb, TCP_PRIO_MIN); 632 tcp_local_port = 80; 633 err = altcp_bind(tcp_server_pcb, IP_ANY_TYPE, tcp_local_port); 634 LWIP_ASSERT("Error: altcp_bind() failed", err == ERR_OK); 635 tcp_server_pcb = altcp_listen(tcp_server_pcb); 636 LWIP_ASSERT("Error: altcp_listen() failed", err == ERR_OK); 637 altcp_accept(tcp_server_pcb, tcp_server_accept); 638 } 639 if (test_apps & LWIP_FUZZ_UDP_CLIENT) { 640 udp_client_pcb = udp_new(); 641 udp_new_ip_type(IPADDR_TYPE_ANY); 642 udp_recv(udp_client_pcb, udp_client_recv, NULL); 643 udp_remote_port = 161; 644 udp_connect(udp_client_pcb, &remote_addr, udp_remote_port); 645 } 646 if (test_apps & LWIP_FUZZ_UDP_SERVER) { 647 udp_server_pcb = udp_new(); 648 udp_new_ip_type(IPADDR_TYPE_ANY); 649 udp_local_port = 161; 650 udp_bind(udp_server_pcb, IP_ANY_TYPE, udp_local_port); 651 udp_recv(udp_server_pcb, udp_server_recv, NULL); 652 } 653 654 if(argc > 1) { 655 FILE* f; 656 const char* filename; 657 printf("reading input from file... "); 658 fflush(stdout); 659 filename = argv[1]; 660 LWIP_ASSERT("invalid filename", filename != NULL); 661 f = fopen(filename, "rb"); 662 LWIP_ASSERT("open failed", f != NULL); 663 len = fread(pktbuf, 1, sizeof(pktbuf), f); 664 fclose(f); 665 printf("testing file: \"%s\"...\r\n", filename); 666 } else { 667 len = fread(pktbuf, 1, sizeof(pktbuf), stdin); 668 } 669 input_pkts(type, &net_test, pktbuf, len); 670 671 pcap_dump_stop(); 672 return 0; 673 } 674 675 #ifdef LWIP_RAND_FOR_FUZZ 676 u32_t lwip_fuzz_rand(void) 677 { 678 #ifdef LWIP_RAND_FOR_FUZZ_SIMULATE_GLIBC 679 /* this is what glibc rand() returns (first 20 numbers) */ 680 static u32_t rand_nrs[] = {0x6b8b4567, 0x327b23c6, 0x643c9869, 0x66334873, 0x74b0dc51, 681 0x19495cff, 0x2ae8944a, 0x625558ec, 0x238e1f29, 0x46e87ccd, 682 0x3d1b58ba, 0x507ed7ab, 0x2eb141f2, 0x41b71efb, 0x79e2a9e3, 683 0x7545e146, 0x515f007c, 0x5bd062c2, 0x12200854, 0x4db127f8}; 684 static unsigned idx = 0; 685 u32_t ret = rand_nrs[idx]; 686 idx++; 687 if (idx >= sizeof(rand_nrs)/sizeof((rand_nrs)[0])) { 688 idx = 0; 689 } 690 return ret; 691 #else 692 /* a simple LCG, unsafe but should give the same result for every execution (best for fuzzing) */ 693 u32_t result; 694 static s32_t state[1] = {0xdeadbeef}; 695 uint64_t val = state[0] & 0xffffffff; 696 val = ((val * 1103515245) + 12345) & 0x7fffffff; 697 state[0] = val; 698 result = val; 699 return result; 700 #endif 701 } 702 #endif 703