TEST_NAME=test
FUZZ=afl-fuzz
LD=$(CC)
-ifeq ($(MODE),client)
- DHCP_C_DEPENDENCY_INJECTION=-include dhcp_di.h
- OBJECTS=dhcp.o network_mock.o test_client.o
- SAMPLE_PACKETS=in_client
-else
- DHCP_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h
- OBJECTS=dhcpserver.o test_server.o network_mock.o
- SAMPLE_PACKETS=in_server
+ifeq ($(MODE),dhcp_client)
+ DEPENDENCY_INJECTION=-include dhcp_di.h
+ OBJECTS=dhcp.o network_mock.o test_dhcp_client.o
+ SAMPLE_PACKETS=in_dhcp_client
+else ifeq ($(MODE),dhcp_server)
+ DEPENDENCY_INJECTION=-include dhcpserver_di.h
+ OBJECTS=dhcpserver.o test_dhcp_server.o network_mock.o
+ SAMPLE_PACKETS=in_dhcp_server
+else ifeq ($(MODE),dns)
+ CFLAGS+=-DNOT_MOCK_DNS
+ DEPENDENCY_INJECTION=-include dns_di.h
+ OBJECTS=dns.o test_dns.o network_mock.o
+ SAMPLE_PACKETS=in_dns
+else
+ $(error Please specify MODE: dhcp_server, dhcp_client, dns)
endif
ifeq ($(INSTR),off)
all: $(TEST_NAME)
+dns.o: ../core/dns.c
+ @echo "[CC] $<"
+ @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
+
dhcp.o: ../core/ipv4/dhcp.c
@echo "[CC] $<"
- @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@
+ @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
dhcpserver.o: ../apps/dhcpserver.c
@echo "[CC] $<"
- @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@
+ @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@
%.o: %.c
@echo "[CC] $<"
--- /dev/null
+/*
+ * dns.c dependecy injection -- preincluded to inject interface test functions into static variables
+ *
+ */
+#include "no_warn_host.h"
+
+#include "lwip/opt.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+#include "lwip/ip_addr.h"
+
+#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr)
+
+extern uint32_t g_random_numbers[8];
+extern uint32_t g_random_numbers_cnt;
+
+void __assert_func(const char *file, int line, const char *func, const char *expr)
+{
+ printf("Assert failed in %s, %s:%d (%s)", func, file, line, expr);
+ abort();
+}
+
+int ip4addr_aton(const char *cp, ip4_addr_t *addr)
+{
+ return 0;
+}
+
+static err_t dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
+static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
+
+void (*dns_test_static_dns_recv)(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) = NULL;
+err_t (*dns_test_static_dns_enqueue)(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) = NULL;
+
+
+void dns_test_init_di()
+{
+ dns_test_static_dns_recv = dns_recv;
+ dns_test_static_dns_enqueue = dns_enqueue;
+}
+
+err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype)
+{
+ return dns_test_static_dns_enqueue(name, hostnamelen, found, callback_arg, dns_addrtype);
+}
+
+void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
+{
+ dns_test_static_dns_recv(s, pcb, p, addr, port);
+}
+
+void dns_test_inject_port_and_txid(int port, int txid)
+{
+ // inject random numbers
+ g_random_numbers[0] = port; //for port
+ g_random_numbers[1] = txid; //for txid
+ g_random_numbers_cnt = 0; // let's start with the port
+}
\ No newline at end of file
const ip_addr_t ip_addr_any;
const ip_addr_t ip_addr_broadcast;
+const ip_addr_t ip_addr_any_type;
struct ip_globals ip_data;
struct netif *netif_list;
+struct udp_pcb mock_pcb;
+uint32_t g_random_numbers[8] = {0};
+uint32_t g_random_numbers_cnt = 0;
+struct pbuf* pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
+{
+ u16_t offset_left = in_offset;
+ struct pbuf* q = in;
+
+ /* get the correct pbuf */
+ while ((q != NULL) && (q->len <= offset_left)) {
+ offset_left -= q->len;
+ q = q->next;
+ }
+ if (out_offset != NULL) {
+ *out_offset = offset_left;
+ }
+ return q;
+}
+
+void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data)
+{
+ u16_t q_idx;
+ struct pbuf* q = pbuf_skip(p, offset, &q_idx);
+
+ /* write requested data if pbuf is OK */
+ if ((q != NULL) && (q->len > q_idx)) {
+ ((u8_t*)q->payload)[q_idx] = data;
+ }
+}
+
+u8_t pbuf_get_at(struct pbuf* p, u16_t offset)
+{
+ u16_t q_idx;
+ struct pbuf* q = pbuf_skip(p, offset, &q_idx);
+
+ /* return requested data if pbuf is OK */
+ if ((q != NULL) && (q->len > q_idx)) {
+ return ((u8_t*)q->payload)[q_idx];
+ }
+ return 0;
+}
+
+err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
+{
+ return ERR_OK;
+}
+
+err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
+{
+ return ERR_OK;
+}
+
+struct udp_pcb * udp_new_ip_type(u8_t type)
+{
+ return &mock_pcb;
+}
+
u16_t lwip_htons(u16_t n)
{
- return 0;
+ return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
u32_t lwip_htonl(u32_t n)
{
- return 0;
+return ((n & 0xff) << 24) |
+ ((n & 0xff00) << 8) |
+ ((n & 0xff0000UL) >> 8) |
+ ((n & 0xff000000UL) >> 24);
}
esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info)
{
- return ESP_OK;
+ return ESP_OK;
}
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
{
}
+#ifndef NOT_MOCK_DNS
void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
{
}
+#endif
uint32_t esp_random(void)
{
- return 0;
+ // Preparation for injecting favorable random numbers
+ return g_random_numbers[g_random_numbers_cnt++ % 8];
}
err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
u32_t lwip_ntohl(u32_t x)
{
- return 0;
+ return lwip_htonl(x);
}
void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
}
}
-u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
+u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
{
+ struct pbuf *p;
+ u16_t left;
+ u16_t buf_copy_len;
+ u16_t copied_total = 0;
+
+ LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
+ LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
+
+ left = 0;
+
+ if ((buf == NULL) || (dataptr == NULL)) {
return 0;
+ }
+
+ /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
+ for (p = buf; len != 0 && p != NULL; p = p->next) {
+ if ((offset != 0) && (offset >= p->len)) {
+ /* don't copy from this buffer -> on to the next */
+ offset -= p->len;
+ } else {
+ /* copy from this buffer. maybe only partially. */
+ buf_copy_len = p->len - offset;
+ if (buf_copy_len > len)
+ buf_copy_len = len;
+ /* copy the necessary parts of the buffer */
+ MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
+ copied_total += buf_copy_len;
+ left += buf_copy_len;
+ len -= buf_copy_len;
+ offset = 0;
+ }
+ }
+ return copied_total;
}
+
err_t udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{
return ESP_OK;
--- /dev/null
+#include "no_warn_host.h"
+
+#include "lwip/opt.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+#include "lwip/ip_addr.h"
+
+#include <string.h>
+
+const ip_addr_t ip_addr_any;
+const ip_addr_t ip_addr_broadcast;
+struct ip_globals ip_data;
+struct netif *netif_list;
+struct netif mynetif;
+ip4_addr_t server_ip;
+
+//
+// Dependency injected test functions
+void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
+void dns_test_inject_port_and_txid(int port, int txid);
+
+void dns_test_init_di();
+err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype);
+
+//
+// Test starts here
+//
+int main(int argc, char** argv)
+{
+ uint8_t *buf;
+ struct pbuf *p;
+ FILE *file;
+ size_t len = 1460;
+
+ dns_test_init_di();
+
+#ifdef INSTR_IS_OFF
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ buf = p->payload;
+ memset(buf, 0, 1460);
+ if (argc != 2)
+ {
+ printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n");
+ return 1;
+ }
+ //
+ // Note: parameter1 is a file (mangled packet) which caused the crash
+ file = fopen(argv[1], "r");
+ if (file) {
+ len = fread(buf, 1, 1460, file);
+ }
+ fclose(file);
+ int i;
+ for (i=0; i<1; i++) {
+#else
+ while (__AFL_LOOP(1000)) {
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ buf = p->payload;
+ memset(buf, 0, 1460);
+ size_t len = read(0, buf, 1460);
+#endif
+ p->len = len;
+ p->tot_len = len;
+ p->next = NULL;
+
+ // Pretend that the response is from our pending querries
+ dns_test_inject_port_and_txid(1024, (buf[0]<<8) + buf[1]);
+ dns_test_dns_enqueue("test", 4, NULL, NULL, 0);
+
+ // Process the packet
+ dns_test_dns_recv(NULL, NULL, p, &ip_addr_any, 0);
+ }
+
+
+
+ return 0;
+}