]> granicus.if.org Git - esp-idf/commitdiff
MDNS-Fuzzer: AFL fuzzer tests for mdsn packet parser
authorDavid Cermak <cermak@espressif.com>
Fri, 4 May 2018 14:42:54 +0000 (16:42 +0200)
committerDavid Cermak <david@Davids-MacBook-Pro.local>
Tue, 22 May 2018 09:23:12 +0000 (11:23 +0200)
components/mdns/include/mdns.h
components/mdns/mdns.c
components/mdns/mdns_networking.c [new file with mode: 0644]
components/mdns/private_include/mdns_networking.h [new file with mode: 0644]
components/mdns/test_afl_fuzz_host/Makefile
components/mdns/test_afl_fuzz_host/esp32_compat.h
components/mdns/test_afl_fuzz_host/esp32_mock.c [new file with mode: 0644]
components/mdns/test_afl_fuzz_host/esp32_mock.h [new file with mode: 0644]
components/mdns/test_afl_fuzz_host/mdns_di.h [new file with mode: 0644]
components/mdns/test_afl_fuzz_host/test.c

index db0e3b522a2eda6e0861f7fe322fc9c906b76b34..a5ebb809f6b2ddda6066b6af5dccc2ddb693a4d0 100644 (file)
 extern "C" {
 #endif
 
-#ifndef MDNS_TEST_MODE
 #include <tcpip_adapter.h>
 #include "esp_event.h"
-#else
-#include "esp32_compat.h"
-#endif
 
 #define MDNS_TYPE_A                 0x0001
 #define MDNS_TYPE_PTR               0x000C
index da00d7e5dbfd7daaeb5e1fdd5f9527e2cc485c7d..73c5f99c9ff36045f9586481c8f439c035673632 100644 (file)
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-#include "mdns.h"
-
-#include <string.h>
-#include "sdkconfig.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/queue.h"
-#include "freertos/semphr.h"
-#include "lwip/ip_addr.h"
-#include "lwip/pbuf.h"
-#include "lwip/igmp.h"
-#include "lwip/udp.h"
-#include "lwip/mld6.h"
-#include "lwip/priv/tcpip_priv.h"
-#include "esp_wifi.h"
-#include "esp_system.h"
-#include "esp_timer.h"
-#include "esp_event_loop.h"
 
+#include "mdns.h"
 #include "mdns_private.h"
+#include "mdns_networking.h"
+#include <string.h>
 
 #ifdef MDNS_ENABLE_DEBUG
 void mdns_debug_packet(const uint8_t * data, size_t len);
@@ -38,7 +24,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len);
 static const char * MDNS_DEFAULT_DOMAIN = "local";
 static const char * MDNS_SUB_STR = "_sub";
 
-static mdns_server_t * _mdns_server = NULL;
+mdns_server_t * _mdns_server = NULL;
 
 static volatile TaskHandle_t _mdns_service_task_handle = NULL;
 static SemaphoreHandle_t _mdns_service_semaphore = NULL;
@@ -110,14 +96,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char
     return NULL;
 }
 
-/*
- * MDNS Server Networking
- * */
-
-/**
- * @brief  Queue RX packet action
- */
-static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
+esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
 {
     mdns_action_t * action = NULL;
 
@@ -135,286 +114,6 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
     return ESP_OK;
 }
 
-/**
- * @brief  the receive callback of the raw udp api. Packets are received here
- *
- */
-static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
-{
-    uint8_t i;
-    while (pb != NULL) {
-        struct pbuf * this_pb = pb;
-        pb = pb->next;
-        this_pb->next = NULL;
-
-        mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
-        if (!packet) {
-            //missed packet - no memory
-            pbuf_free(this_pb);
-            continue;
-        }
-
-        packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
-        packet->pb = this_pb;
-        packet->src_port = rport;
-        memcpy(&packet->src, raddr, sizeof(ip_addr_t));
-        packet->dest.type = packet->src.type;
-
-        if (packet->src.type == IPADDR_TYPE_V4) {
-            packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
-            struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
-            packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
-        } else {
-            packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
-            struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
-            memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
-        }
-        packet->multicast = ip_addr_ismulticast(&(packet->dest));
-
-        //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
-        struct netif * netif = NULL;
-        void * nif = NULL;
-        struct udp_pcb * pcb = NULL;
-        for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
-            pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
-            tcpip_adapter_get_netif (i, &nif);
-            netif = (struct netif *)nif;
-            if (pcb && netif && netif == ip_current_input_netif ()) {
-                if (packet->src.type == IPADDR_TYPE_V4) {
-                    if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) {
-                        //packet source is not in the same subnet
-                        pcb = NULL;
-                        break;
-                    }
-                }
-                packet->tcpip_if = i;
-                break;
-            }
-            pcb = NULL;
-        }
-
-        if (!pcb || !_mdns_server || !_mdns_server->action_queue
-          || _mdns_send_rx_action(packet) != ESP_OK) {
-            pbuf_free(this_pb);
-            free(packet);
-        }
-    }
-}
-
-/**
- * @brief  Stop PCB Main code
- */
-static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
-{
-    if (!_mdns_server) {
-        return;
-    }
-    mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
-    if (_pcb->pcb) {
-        _pcb->state = PCB_OFF;
-        udp_recv(_pcb->pcb, NULL, NULL);
-        udp_disconnect(_pcb->pcb);
-        udp_remove(_pcb->pcb);
-        free(_pcb->probe_services);
-        _pcb->pcb = NULL;
-        _pcb->probe_ip = false;
-        _pcb->probe_services = NULL;
-        _pcb->probe_services_len = 0;
-        _pcb->probe_running = false;
-        _pcb->failed_probes = 0;
-    }
-}
-
-/**
- * @brief  Start PCB V4
- */
-static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if)
-{
-    tcpip_adapter_ip_info_t if_ip_info;
-
-    if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr);
-
-    ip_addr_t multicast_addr;
-    IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
-
-    if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4);
-    if (!pcb) {
-        return ESP_ERR_NO_MEM;
-    }
-
-    if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
-        udp_remove(pcb);
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    pcb->mcast_ttl = 1;
-    pcb->remote_port = MDNS_SERVICE_PORT;
-    ip_addr_copy(pcb->multicast_ip, interface_addr);
-    ip_addr_copy(pcb->remote_ip, multicast_addr);
-
-    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb;
-    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0;
-    udp_recv(pcb, &_udp_recv, _mdns_server);
-
-    return ESP_OK;
-}
-
-/**
- * @brief  Start PCB V6
- */
-static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if)
-{
-    ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
-    ip_addr_t interface_addr;
-    interface_addr.type = IPADDR_TYPE_V6;
-
-    if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6);
-    if (!pcb) {
-        return ESP_ERR_NO_MEM;
-    }
-
-    if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
-        udp_remove(pcb);
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    pcb->remote_port = MDNS_SERVICE_PORT;
-    ip_addr_copy(pcb->remote_ip, multicast_addr);
-
-    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb;
-    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0;
-    udp_recv(pcb, &_udp_recv, _mdns_server);
-
-    return ESP_OK;
-}
-
-/**
- * @brief  Start PCB Main code
- */
-static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
-{
-    if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
-        return _udp_pcb_v4_init(tcpip_if);
-    } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) {
-        return _udp_pcb_v6_init(tcpip_if);
-    }
-    return ESP_ERR_INVALID_ARG;
-}
-
-typedef struct {
-    struct tcpip_api_call call;
-    tcpip_adapter_if_t tcpip_if;
-    mdns_ip_protocol_t ip_protocol;
-    esp_err_t err;
-} mdns_api_call_t;
-
-/**
- * @brief  Start PCB from LwIP thread
- */
-static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg)
-{
-    mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
-    msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
-    return msg->err;
-}
-
-/**
- * @brief  Start PCB
- */
-static esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
-{
-    mdns_api_call_t msg = {
-        .tcpip_if = tcpip_if,
-        .ip_protocol = ip_protocol
-    };
-    tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg);
-    return msg.err;
-}
-
-/**
- * @brief  Stop PCB from LwIP thread
- */
-static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg)
-{
-    mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
-    _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
-    msg->err = ESP_OK;
-    return ESP_OK;
-}
-
-/**
- * @brief  Stop PCB
- */
-static esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
-{
-    mdns_api_call_t msg = {
-        .tcpip_if = tcpip_if,
-        .ip_protocol = ip_protocol
-    };
-    tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg);
-    return msg.err;
-}
-
-
-/**
- * @brief  send packet over UDP
- *
- * @param  server       The server
- * @param  data         byte array containing the packet data
- * @param  len          length of the packet data
- *
- * @return length of sent packet or 0 on error
- */
-static size_t _udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len)
-{
-#ifndef MDNS_TEST_MODE
-    struct netif * netif = NULL;
-    void * nif = NULL;
-    esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
-    netif = (struct netif *)nif;
-    if (err) {
-        return 0;
-    }
-
-    struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
-    if (pbt == NULL) {
-        return 0;
-    }
-    memcpy((uint8_t *)pbt->payload, data, len);
-
-    err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif);
-    pbuf_free(pbt);
-    if (err) {
-        return 0;
-    }
-#endif
-    return len;
-}
-
 /**
  * @brief  Get the service name of a service
  */
@@ -1235,7 +934,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p)
     mdns_debug_packet(packet, index);
 #endif
 
-    _udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index);
+    _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index);
 }
 
 /**
@@ -4192,7 +3891,6 @@ static esp_err_t _mdns_stop_timer(){
  */
 static esp_err_t _mdns_service_task_start()
 {
-#ifndef MDNS_TEST_MODE
     if (!_mdns_service_semaphore) {
         _mdns_service_semaphore = xSemaphoreCreateMutex();
         if (!_mdns_service_semaphore) {
@@ -4212,8 +3910,6 @@ static esp_err_t _mdns_service_task_start()
         }
     }
     MDNS_SERVICE_UNLOCK();
-#endif
-
     return ESP_OK;
 }
 
@@ -4225,7 +3921,6 @@ static esp_err_t _mdns_service_task_start()
  */
 static esp_err_t _mdns_service_task_stop()
 {
-#ifndef MDNS_TEST_MODE
     MDNS_SERVICE_LOCK();
     _mdns_stop_timer();
     if (_mdns_service_task_handle) {
@@ -4241,7 +3936,6 @@ static esp_err_t _mdns_service_task_stop()
         }
     }
     MDNS_SERVICE_UNLOCK();
-#endif
     return ESP_OK;
 }
 
diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c
new file mode 100644 (file)
index 0000000..e4ab816
--- /dev/null
@@ -0,0 +1,284 @@
+
+/*
+ * MDNS Server Networking
+ * 
+ */
+#include <string.h>
+#include "mdns_networking.h"
+
+
+extern mdns_server_t * _mdns_server;
+
+/*
+ * MDNS Server Networking
+ *
+ */
+
+/**
+ * @brief  the receive callback of the raw udp api. Packets are received here
+ *
+ */
+static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
+{
+
+    uint8_t i;
+    while (pb != NULL) {
+        struct pbuf * this_pb = pb;
+        pb = pb->next;
+        this_pb->next = NULL;
+
+        mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
+        if (!packet) {
+            //missed packet - no memory
+            pbuf_free(this_pb);
+            continue;
+        }
+
+        packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
+        packet->pb = this_pb;
+        packet->src_port = rport;
+        memcpy(&packet->src, raddr, sizeof(ip_addr_t));
+        packet->dest.type = packet->src.type;
+
+        if (packet->src.type == IPADDR_TYPE_V4) {
+            packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
+            struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
+            packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
+        } else {
+            packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
+            struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
+            memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
+        }
+        packet->multicast = ip_addr_ismulticast(&(packet->dest));
+
+        //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
+        struct netif * netif = NULL;
+        void * nif = NULL;
+        struct udp_pcb * pcb = NULL;
+        for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
+            pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
+            tcpip_adapter_get_netif (i, &nif);
+            netif = (struct netif *)nif;
+            if (pcb && netif && netif == ip_current_input_netif ()) {
+                if (packet->src.type == IPADDR_TYPE_V4) {
+                    if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) {
+                        //packet source is not in the same subnet
+                        pcb = NULL;
+                        break;
+                    }
+                }
+                packet->tcpip_if = i;
+                break;
+            }
+            pcb = NULL;
+        }
+
+        if (!pcb || !_mdns_server || !_mdns_server->action_queue
+          || _mdns_send_rx_action(packet) != ESP_OK) {
+            pbuf_free(this_pb);
+            free(packet);
+        }
+    }
+
+}
+
+/**
+ * @brief  Stop PCB Main code
+ */
+static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
+{
+    if (!_mdns_server) {
+        return;
+    }
+    mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
+    if (_pcb->pcb) {
+        _pcb->state = PCB_OFF;
+        udp_recv(_pcb->pcb, NULL, NULL);
+        udp_disconnect(_pcb->pcb);
+        udp_remove(_pcb->pcb);
+        free(_pcb->probe_services);
+        _pcb->pcb = NULL;
+        _pcb->probe_ip = false;
+        _pcb->probe_services = NULL;
+        _pcb->probe_services_len = 0;
+        _pcb->probe_running = false;
+        _pcb->failed_probes = 0;
+    }
+}
+
+/**
+ * @brief  Start PCB V4
+ */
+static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if)
+{
+    tcpip_adapter_ip_info_t if_ip_info;
+
+    if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr);
+
+    ip_addr_t multicast_addr;
+    IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
+
+    if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4);
+    if (!pcb) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
+        udp_remove(pcb);
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    pcb->mcast_ttl = 1;
+    pcb->remote_port = MDNS_SERVICE_PORT;
+    ip_addr_copy(pcb->multicast_ip, interface_addr);
+    ip_addr_copy(pcb->remote_ip, multicast_addr);
+
+    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb;
+    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0;
+    udp_recv(pcb, &_udp_recv, _mdns_server);
+
+    return ESP_OK;
+}
+
+/**
+ * @brief  Start PCB V6
+ */
+static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if)
+{
+    ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
+    ip_addr_t interface_addr;
+    interface_addr.type = IPADDR_TYPE_V6;
+
+    if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6);
+    if (!pcb) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
+        udp_remove(pcb);
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    pcb->remote_port = MDNS_SERVICE_PORT;
+    ip_addr_copy(pcb->remote_ip, multicast_addr);
+
+    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb;
+    _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0;
+    udp_recv(pcb, &_udp_recv, _mdns_server);
+
+    return ESP_OK;
+}
+
+/**
+ * @brief  Start PCB Main code
+ */
+static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
+{
+    if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
+        return _udp_pcb_v4_init(tcpip_if);
+    } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) {
+        return _udp_pcb_v6_init(tcpip_if);
+    }
+    return ESP_ERR_INVALID_ARG;
+}
+
+typedef struct {
+    struct tcpip_api_call call;
+    tcpip_adapter_if_t tcpip_if;
+    mdns_ip_protocol_t ip_protocol;
+    esp_err_t err;
+} mdns_api_call_t;
+
+/**
+ * @brief  Start PCB from LwIP thread
+ */
+static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg)
+{
+    mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
+    msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
+    return msg->err;
+}
+
+/**
+ * @brief  Stop PCB from LwIP thread
+ */
+static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg)
+{
+    mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
+    _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
+    msg->err = ESP_OK;
+    return ESP_OK;
+}
+
+/*
+ * Non-static functions below are
+ *  - _mdns prefixed
+ *  - commented in mdns_networking.h header
+ */
+esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
+{
+    mdns_api_call_t msg = {
+        .tcpip_if = tcpip_if,
+        .ip_protocol = ip_protocol
+    };
+    tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg);
+    return msg.err;
+}
+
+esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
+{
+    mdns_api_call_t msg = {
+        .tcpip_if = tcpip_if,
+        .ip_protocol = ip_protocol
+    };
+    tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg);
+    return msg.err;
+}
+
+size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len)
+{
+    struct netif * netif = NULL;
+    void * nif = NULL;
+    esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
+    netif = (struct netif *)nif;
+    if (err) {
+        return 0;
+    }
+
+    struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
+    if (pbt == NULL) {
+        return 0;
+    }
+    memcpy((uint8_t *)pbt->payload, data, len);
+
+    err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif);
+    pbuf_free(pbt);
+    if (err) {
+        return 0;
+    }
+    return len;
+}
diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h
new file mode 100644 (file)
index 0000000..5b56f80
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef ESP_MDNS_NETWORKING_H_
+#define ESP_MDNS_NETWORKING_H_
+
+/*
+ * MDNS Server Networking -- private include
+ * 
+ */
+#include "mdns.h"
+#include "mdns_private.h"
+#include "sdkconfig.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "lwip/ip_addr.h"
+#include "lwip/pbuf.h"
+#include "lwip/igmp.h"
+#include "lwip/udp.h"
+#include "lwip/mld6.h"
+#include "lwip/priv/tcpip_priv.h"
+#include "esp_wifi.h"
+#include "esp_system.h"
+#include "esp_timer.h"
+#include "esp_event_loop.h"
+
+
+/**
+ * @brief  Queue RX packet action
+ */
+esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet);
+
+/**
+ * @brief  Start PCB
+ */
+esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
+
+/**
+ * @brief  Stop PCB
+ */
+esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
+
+/**
+ * @brief  send packet over UDP
+ *
+ * @param  server       The server
+ * @param  data         byte array containing the packet data
+ * @param  len          length of the packet data
+ *
+ * @return length of sent packet or 0 on error
+ */
+size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len);
+
+#endif /* ESP_MDNS_NETWORKING_H_ */
index 65a318ef241591d2e1639aa477959d598f4e7135..61bedc52092cbb4be0d657d94adffa1f4a7c843c 100644 (file)
@@ -1,17 +1,25 @@
 TEST_NAME=test
 FUZZ=afl-fuzz
-CC=afl-clang-fast
+COMPONENTS_DIR=../..
+CFLAGS=-g -DMDNS_TEST_MODE -I. -I.. -I../include -I../private_include -I$(COMPONENTS_DIR)/tcpip_adapter/include -I$(COMPONENTS_DIR)/esp32/include -include esp32_compat.h
+MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h
+ifeq ($(INSTR),off)
+    CC=gcc
+    CFLAGS+=-DINSTR_IS_OFF
+    TEST_NAME=test_sim
+else
+    CC=afl-clang-fast
+endif
 CPP=$(CC)
 LD=$(CC)
-OBJECTS=mdns.o test.o
-CFLAGS=-DMDNS_TEST_MODE -I. -I../include
+OBJECTS=mdns.o esp32_mock.o test.o
 
 OS := $(shell uname)
 ifeq ($(OS),Darwin)
   LDLIBS=
 else
-  LDLIBS=-lbsd
-  CFLAGS+=-DUSE_BSD_STRING
+   LDLIBS=-lbsd
+   CFLAGS+=-DUSE_BSD_STRING
 endif
 
 all: $(TEST_NAME)
@@ -22,11 +30,11 @@ all: $(TEST_NAME)
 
 mdns.o: ../mdns.c
        @echo "[CC] $<"
-       @$(CC) $(CFLAGS) -c $< -o $@
+       @$(CC) $(CFLAGS) $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@
 
 $(TEST_NAME): $(OBJECTS)
        @echo "[LD] $@"
-       @$(LD) $(LDLIBS) $(OBJECTS) -o $@
+       @$(LD)  $(OBJECTS) -o $@ $(LDLIBS)
 
 fuzz: $(TEST_NAME)
        @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME)
index fd21b23657a88c6ba0a47628f79960311ad27f9d..402807c4f58a494c7a9129bc6f91e7ed10208222 100644 (file)
 
 #ifdef MDNS_TEST_MODE
 
+// Not to include
+#define ESP_MDNS_NETWORKING_H_
+#define _TCPIP_ADAPTER_H_
+#define __ESP_EVENT_H__
+
+
 #ifdef USE_BSD_STRING
 #include <bsd/string.h>
 #endif
@@ -28,6 +34,7 @@
 #include <signal.h>
 #include <sys/time.h>
 
+
 #define ERR_OK                      0
 #define ESP_OK                      0
 #define ESP_FAIL                    -1
 
 #define pdTRUE                      true
 #define pdFALSE                     false
+#define pdPASS                 ( pdTRUE )
+#define pdFAIL                 ( pdFALSE )
 
 #define portMAX_DELAY               0xFFFFFFFF
 #define portTICK_PERIOD_MS          1
 
 #define xSemaphoreTake(s,d)
+#define xTaskDelete(a)
+#define vTaskDelete(a)             free(a)
 #define xSemaphoreGive(s)
+#define _mdns_pcb_init(a,b)         true
+#define _mdns_pcb_deinit(a,b)         true
 #define xSemaphoreCreateMutex()     malloc(1)
 #define vSemaphoreDelete(s)         free(s)
-#define xQueueCreate(n,s)           malloc((n)*(s))
-#define vQueueDelete(q)             free(q)
-#define xQueueReceive(q, d, t)      (ESP_OK)
-#define vTaskDelay(m)               usleep((m)*1000)
+#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g)     *(f) = malloc(1)
+#define vTaskDelay(m)               usleep((m)*0)
 #define pbuf_free(p)                free(p)
-
-#define tcpip_adapter_get_ip_info(i,d)
+#define esp_random()                (rand()%UINT32_MAX)
+#define tcpip_adapter_get_ip_info(i,d)          true
+#define tcpip_adapter_dhcpc_get_status(a, b)    TCPIP_ADAPTER_DHCP_STARTED
 #define tcpip_adapter_get_ip6_linklocal(i,d)    (ESP_OK)
 #define tcpip_adapter_get_hostname(i, n)        *(n) = "esp32-0123456789AB"
 
                          ((uint32_t)((c) & 0xff) << 16) | \
                          ((uint32_t)((b) & 0xff) << 8)  | \
                           (uint32_t)((a) & 0xff)
+#define ip_2_ip6(ipaddr)   (&((ipaddr)->u_addr.ip6))
+#define ip_2_ip4(ipaddr)   (&((ipaddr)->u_addr.ip4))
+
+#define IPADDR_TYPE_V4                0U
+#define IPADDR_TYPE_V6                6U
+#define IPADDR_TYPE_ANY               46U
+#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0)
+#define IP_ADDR4(ipaddr,a,b,c,d)      do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \
+                                           IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0)
+#define IP_ADDR6(ipaddr,i0,i1,i2,i3)  do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \
+                                           IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0)
+
+#define IPADDR6_INIT(a, b, c, d)      { { { { a, b, c, d } } }, IPADDR_TYPE_V6 }
+
 typedef int32_t esp_err_t;
 
 typedef void * xSemaphoreHandle;
+typedef void * SemaphoreHandle_t;
 typedef void * xQueueHandle;
+typedef void * QueueHandle_t;
+typedef void * TaskHandle_t;
+typedef void * esp_timer_handle_t;
+typedef uint32_t TickType_t;
+typedef uint32_t portTickType;
 
-typedef enum {
-    TCPIP_ADAPTER_IF_STA = 0,     /**< ESP32 station interface */
-    TCPIP_ADAPTER_IF_AP,          /**< ESP32 soft-AP interface */
-    TCPIP_ADAPTER_IF_ETH,         /**< ESP32 ethernet interface */
-    TCPIP_ADAPTER_IF_MAX
-} tcpip_adapter_if_t;
 
 typedef enum {
     WIFI_MODE_NULL = 0,  /**< null mode */
@@ -87,6 +113,42 @@ typedef enum {
     WIFI_MODE_MAX
 } wifi_mode_t;
 
+/* status of DHCP client or DHCP server */
+typedef enum {
+    TCPIP_ADAPTER_DHCP_INIT = 0,    /**< DHCP client/server in initial state */
+    TCPIP_ADAPTER_DHCP_STARTED,     /**< DHCP client/server already been started */
+    TCPIP_ADAPTER_DHCP_STOPPED,     /**< DHCP client/server already been stopped */
+    TCPIP_ADAPTER_DHCP_STATUS_MAX
+} tcpip_adapter_dhcp_status_t;
+
+typedef enum {
+    SYSTEM_EVENT_WIFI_READY = 0,           /**< ESP32 WiFi ready */
+    SYSTEM_EVENT_SCAN_DONE,                /**< ESP32 finish scanning AP */
+    SYSTEM_EVENT_STA_START,                /**< ESP32 station start */
+    SYSTEM_EVENT_STA_STOP,                 /**< ESP32 station stop */
+    SYSTEM_EVENT_STA_CONNECTED,            /**< ESP32 station connected to AP */
+    SYSTEM_EVENT_STA_DISCONNECTED,         /**< ESP32 station disconnected from AP */
+    SYSTEM_EVENT_STA_AUTHMODE_CHANGE,      /**< the auth mode of AP connected by ESP32 station changed */
+    SYSTEM_EVENT_STA_GOT_IP,               /**< ESP32 station got IP from connected AP */
+    SYSTEM_EVENT_STA_LOST_IP,              /**< ESP32 station lost IP and the IP is reset to 0 */
+    SYSTEM_EVENT_STA_WPS_ER_SUCCESS,       /**< ESP32 station wps succeeds in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_FAILED,        /**< ESP32 station wps fails in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_TIMEOUT,       /**< ESP32 station wps timeout in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_PIN,           /**< ESP32 station wps pin code in enrollee mode */
+    SYSTEM_EVENT_AP_START,                 /**< ESP32 soft-AP start */
+    SYSTEM_EVENT_AP_STOP,                  /**< ESP32 soft-AP stop */
+    SYSTEM_EVENT_AP_STACONNECTED,          /**< a station connected to ESP32 soft-AP */
+    SYSTEM_EVENT_AP_STADISCONNECTED,       /**< a station disconnected from ESP32 soft-AP */
+    SYSTEM_EVENT_AP_PROBEREQRECVED,        /**< Receive probe request packet in soft-AP interface */
+    SYSTEM_EVENT_GOT_IP6,                  /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
+    SYSTEM_EVENT_ETH_START,                /**< ESP32 ethernet start */
+    SYSTEM_EVENT_ETH_STOP,                 /**< ESP32 ethernet stop */
+    SYSTEM_EVENT_ETH_CONNECTED,            /**< ESP32 ethernet phy link up */
+    SYSTEM_EVENT_ETH_DISCONNECTED,         /**< ESP32 ethernet phy link down */
+    SYSTEM_EVENT_ETH_GOT_IP,               /**< ESP32 ethernet got IP from connected AP */
+    SYSTEM_EVENT_MAX
+} system_event_id_t;
+
 struct udp_pcb {
     uint8_t dummy;
 };
@@ -101,27 +163,76 @@ struct ip6_addr {
 };
 typedef struct ip6_addr ip6_addr_t;
 
+typedef struct _ip_addr {
+  union {
+    ip6_addr_t ip6;
+    ip4_addr_t ip4;
+  } u_addr;
+  uint8_t type;
+} ip_addr_t;
+
 typedef struct {
     ip4_addr_t ip;
     ip4_addr_t netmask;
     ip4_addr_t gw;
 } tcpip_adapter_ip_info_t;
 
+// typedef int32_t system_event_id_t;
+typedef enum {
+    TCPIP_ADAPTER_IF_STA = 0,     /**< ESP32 station interface */
+    TCPIP_ADAPTER_IF_AP,          /**< ESP32 soft-AP interface */
+    TCPIP_ADAPTER_IF_ETH,         /**< ESP32 ethernet interface */
+    TCPIP_ADAPTER_IF_MAX
+} tcpip_adapter_if_t;
+
+typedef struct {
+    ip6_addr_t ip;
+} tcpip_adapter_ip6_info_t;
+typedef struct {
+    tcpip_adapter_if_t if_index;
+    tcpip_adapter_ip6_info_t ip6_info;
+} system_event_got_ip6_t;
+typedef union {
+    system_event_got_ip6_t                     got_ip6;            /**< ESP32 station or ap or ethernet ipv6 addr state change to preferred */
+} system_event_info_t;
+
+typedef struct {
+    system_event_id_t     event_id;      /**< event ID */
+    system_event_info_t   event_info;    /**< event information */
+} system_event_t;
+
 inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode)
 {
     *mode = WIFI_MODE_APSTA;
     return ESP_OK;
 }
 
-inline uint32_t xTaskGetTickCount()
-{
-    struct timeval tv;
-    struct timezone tz;
-    if (gettimeofday(&tv, &tz) == 0) {
-        return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-    }
-    return 0;
-}
+struct pbuf {
+  struct pbuf *next;
+  void *payload;
+  uint16_t tot_len;
+  uint16_t  len;
+  uint8_t  /*pbuf_type*/ type;
+  uint8_t  flags;
+  uint16_t  ref;
+};
+
+#define IP_GET_TYPE(ipaddr)           ((ipaddr)->type)
+#define IP_IS_V6_VAL(ipaddr)          (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6)
+#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
+#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \
+                                    (dest).addr[1] = (src).addr[1]; \
+                                    (dest).addr[2] = (src).addr[2]; \
+                                    (dest).addr[3] = (src).addr[3];}while(0)
+
+#define ip_addr_copy(dest, src)      do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
+  ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
+  ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0)
+
+#include "esp32_mock.h"
+
+uint32_t xTaskGetTickCount();
+
 
 #endif //MDNS_TEST_MODE
 
diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c
new file mode 100644 (file)
index 0000000..aa9ca7f
--- /dev/null
@@ -0,0 +1,84 @@
+#include <stdio.h>\r
+#include <string.h>\r
+#include <pthread.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include "esp32_compat.h"\r
+\r
+void*     g_queue;\r
+int       g_queue_send_shall_fail = 0;\r
+int       g_size = 0;\r
+\r
+esp_err_t esp_timer_delete(esp_timer_handle_t timer)\r
+{\r
+    return ESP_OK;\r
+}\r
+\r
+esp_err_t esp_timer_stop(esp_timer_handle_t timer)\r
+{\r
+    return ESP_OK;\r
+}\r
+\r
+esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period)\r
+{\r
+    return ESP_OK;\r
+}\r
+\r
+esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,\r
+                           esp_timer_handle_t* out_handle)\r
+{\r
+    return ESP_OK;\r
+}\r
+\r
+uint32_t xTaskGetTickCount()\r
+{\r
+    struct timeval tv;\r
+    struct timezone tz;\r
+    if (gettimeofday(&tv, &tz) == 0) {\r
+        return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);\r
+    }\r
+    return 0;\r
+}\r
+\r
+/// Queue mock\r
+ QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize )\r
+ {\r
+     g_size = uxItemSize;\r
+     g_queue = malloc((uxQueueLength)*(uxItemSize));\r
+     return g_queue;\r
+ }\r
+\r
+\r
+void vQueueDelete( QueueHandle_t xQueue )\r
+{\r
+    free(xQueue);\r
+}\r
+\r
+uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait)\r
+{\r
+    if (g_queue_send_shall_fail)\r
+    {\r
+        return pdFALSE;\r
+    }\r
+    else\r
+    {\r
+        memcpy(xQueue, pvItemToQueue, g_size);\r
+        return pdPASS;\r
+    }\r
+}\r
+\r
+\r
+uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)\r
+{\r
+    return pdFALSE;\r
+}\r
+\r
+void GetLastItem(void *pvBuffer)\r
+{\r
+    memcpy(pvBuffer, g_queue, g_size);\r
+}\r
+\r
+void ForceTaskDelete()\r
+{\r
+    g_queue_send_shall_fail = 1;\r
+}\r
diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h
new file mode 100644 (file)
index 0000000..7246e29
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef ESP32_MOCK_H_\r
+#define ESP32_MOCK_H_\r
+\r
+typedef void (*esp_timer_cb_t)(void* arg);\r
+\r
+typedef enum \r
+{\r
+    ESP_TIMER_TASK,     //!< Callback is called from timer task\r
+} esp_timer_dispatch_t;\r
+\r
+typedef struct \r
+{\r
+    esp_timer_cb_t callback;        //!< Function to call when timer expires\r
+    void* arg;                      //!< Argument to pass to the callback\r
+    esp_timer_dispatch_t dispatch_method;   //!< Call the callback from task or from ISR\r
+    const char* name;               //!< Timer name, used in esp_timer_dump function\r
+} esp_timer_create_args_t;\r
+\r
+esp_err_t esp_timer_delete(esp_timer_handle_t timer);\r
+\r
+esp_err_t esp_timer_stop(esp_timer_handle_t timer);\r
+\r
+esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period);\r
+\r
+esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,\r
+                           esp_timer_handle_t* out_handle);\r
+\r
+\r
+// Queue mock\r
+ QueueHandle_t xQueueCreate( uint32_t uxQueueLength,\r
+                             uint32_t uxItemSize );\r
+\r
+void vQueueDelete( QueueHandle_t xQueue );\r
+\r
+uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);\r
+\r
+uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);\r
+\r
+void GetLastItem(void *pvBuffer);\r
+\r
+void ForceTaskDelete();\r
+\r
+#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len\r
+\r
+#endif /* ESP32_MOCK_H_ */
\ No newline at end of file
diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h
new file mode 100644 (file)
index 0000000..05aeb8b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables
+ * 
+ */
+
+#include "mdns.h"
+#include "mdns_private.h"
+
+void              (*mdns_test_static_execute_action)(mdns_action_t *) = NULL;
+mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto) = NULL;
+mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL;
+esp_err_t         (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL;
+void              (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL;
+
+static void _mdns_execute_action(mdns_action_t * action);
+static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto);
+static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results);
+static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search);
+static void _mdns_search_free(mdns_search_once_t * search);
+
+void mdns_test_init_di()
+{
+    mdns_test_static_execute_action = _mdns_execute_action;
+    mdns_test_static_mdns_get_service_item = _mdns_get_service_item;
+    mdns_test_static_search_init = _mdns_search_init;
+    mdns_test_static_send_search_action = _mdns_send_search_action;
+    mdns_test_static_search_free = _mdns_search_free;
+}
+
+void mdns_test_execute_action(void * action)
+{
+    mdns_test_static_execute_action((mdns_action_t *)action);
+}
+
+void mdns_test_search_free(mdns_search_once_t * search)
+{
+    return mdns_test_static_search_free(search);
+}
+
+esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search)
+{
+    return mdns_test_static_send_search_action(type, search);
+}
+
+mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results)
+{
+    return mdns_test_static_search_init(name, service, proto, type, timeout, max_results);
+}
+
+mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto)
+{
+    return mdns_test_static_mdns_get_service_item(service, proto);
+}
\ No newline at end of file
index be06ac0bfe51474e90f5db1f7b1bf0a74f24ea9d..8ea72d95c17f6721ca6fd74617c7fdb7a24dcff7 100644 (file)
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifdef MDNS_TEST_MODE
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 
 #include "mdns.h"
+#include "mdns_private.h"
+
+//
+// Global stuctures containing packet payload, search
+mdns_rx_packet_t g_packet;
+struct pbuf mypbuf;
+mdns_search_once_t * search = NULL;
+
+//
+// Dependency injected test functions
+void mdns_test_execute_action(void * action);
+mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto);
+mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results);
+esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search);
+void mdns_test_search_free(mdns_search_once_t * search);
+void mdns_test_init_di();
+
+//
+// mdns function wrappers for mdns setup in test mode
+static int mdns_test_hostname_set(const char * mdns_hostname)
+{
+    int ret = mdns_hostname_set(mdns_hostname);
+    mdns_action_t * a = NULL;
+    GetLastItem(&a);
+    mdns_test_execute_action(a);
+    return ret;
+}
+
+static int mdns_test_service_instance_name_set(const char * service, const char * proto, const char * instance)
+{
+    int ret = mdns_service_instance_name_set(service, proto, instance);
+    mdns_action_t * a = NULL;
+    GetLastItem(&a);
+    mdns_test_execute_action(a);
+    return ret;
+}
+
+static int mdns_test_service_txt_set(const char * service, const char * proto,  uint8_t num_items, mdns_txt_item_t txt[])
+{
+    int ret = mdns_service_txt_set(service, proto, txt, num_items);
+    mdns_action_t * a = NULL;
+    GetLastItem(&a);
+    mdns_test_execute_action(a);
+    return ret;
+}
 
-void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len);
+static int mdns_test_service_add(const char * service_name, const char * proto, uint32_t port)
+{
+    if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
+        // This is expected failure as the service thread is not running
+    }
+    mdns_action_t * a = NULL;
+    GetLastItem(&a);
+    mdns_test_execute_action(a);
+
+    if (mdns_test_mdns_get_service_item(service_name, proto)==NULL) {
+        return ESP_FAIL;
+    }
+    return ESP_OK;
+}
 
+static mdns_result_t* mdns_test_query(const char * service_name, const char * proto)
+{
+    search = mdns_test_search_init(NULL, service_name, proto, MDNS_TYPE_PTR, 3000, 20);
+    if (!search) {
+        abort();
+    }
+
+    if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) {
+        mdns_test_search_free(search);
+        abort();
+    }
+
+    mdns_action_t * a = NULL;
+    GetLastItem(&a);
+    mdns_test_execute_action(a);
+    return NULL;
+}
+
+static void mdns_test_query_free()
+{
+    mdns_test_search_free(search);
+}
+
+//
+// function "under test" where afl-mangled packets passed
+//
+void mdns_parse_packet(mdns_rx_packet_t * packet);
+
+//
+// Test starts here
+//
 int main(int argc, char** argv)
 {
+    int i;
     const char * mdns_hostname = "minifritz";
     const char * mdns_instance = "Hristo's Time Capsule";
-    const char * arduTxtData[4] = {
-        "board=esp32",
-        "tcp_check=no",
-        "ssh_upload=no",
-        "auth_upload=no"
+    mdns_txt_item_t arduTxtData[4] = {
+        {"board","esp32"},
+        {"tcp_check","no"},
+        {"ssh_upload","no"},
+        {"auth_upload","no"}
     };
+
     const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32};
     
-    mdns_server_t * mdns = NULL;
     uint8_t buf[1460];
     char winstance[21+strlen(mdns_hostname)];
 
     sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 
-    if (mdns_init(TCPIP_ADAPTER_IF_ETH, &mdns)) {
-        abort();
-    }
+    // Init depencency injected methods
+    mdns_test_init_di();
 
-    if (mdns_set_hostname(mdns, mdns_hostname)) {
+    if (mdns_init()) {
         abort();
     }
 
-    if (mdns_set_instance(mdns, mdns_instance)) {
+    if (mdns_test_hostname_set(mdns_hostname)) {
         abort();
     }
 
-    if (mdns_service_add(mdns, "_workstation", "_tcp", 9)) {
+    if (mdns_test_service_add("_workstation", "_tcp", 9)) {
         abort();
     }
-
-    if (mdns_service_instance_set(mdns, "_workstation", "_tcp", winstance)) {
+    if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) {
         abort();
     }
 
-    if (mdns_service_add(mdns, "_arduino", "_tcp", 3232)) {
+    if (mdns_test_service_add("_arduino", "_tcp", 3232)) {
         abort();
     }
 
-    if (mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData)) {
+    if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) {
         abort();
     }
 
-    if (mdns_service_add(mdns, "_http", "_tcp", 80)) {
+    if (mdns_test_service_add("_http", "_tcp", 80)) {
         abort();
     }
 
-    if (mdns_service_instance_set(mdns, "_http", "_tcp", "ESP WebServer")) {
+    if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) {
         abort();
     }
 
     if (
-           mdns_service_add(mdns, "_afpovertcp", "_tcp", 548)
-        || mdns_service_add(mdns, "_rfb", "_tcp", 885)
-        || mdns_service_add(mdns, "_smb", "_tcp", 885)
-        || mdns_service_add(mdns, "_adisk", "_tcp", 885)
-        || mdns_service_add(mdns, "_airport", "_tcp", 885)
-        || mdns_service_add(mdns, "_printer", "_tcp", 885)
-        || mdns_service_add(mdns, "_airplay", "_tcp", 885)
-        || mdns_service_add(mdns, "_raop", "_tcp", 885)
-        || mdns_service_add(mdns, "_uscan", "_tcp", 885)
-        || mdns_service_add(mdns, "_uscans", "_tcp", 885)
-        || mdns_service_add(mdns, "_ippusb", "_tcp", 885)
-        || mdns_service_add(mdns, "_scanner", "_tcp", 885)
-        || mdns_service_add(mdns, "_ipp", "_tcp", 885)
-        || mdns_service_add(mdns, "_ipps", "_tcp", 885)
-        || mdns_service_add(mdns, "_pdl-datastream", "_tcp", 885)
-        || mdns_service_add(mdns, "_ptp", "_tcp", 885)
-        || mdns_service_add(mdns, "_sleep-proxy", "_udp", 885))
+           mdns_test_service_add("_afpovertcp", "_tcp", 548)
+        || mdns_test_service_add("_rfb", "_tcp", 885)
+        || mdns_test_service_add("_smb", "_tcp", 885)
+        || mdns_test_service_add("_adisk", "_tcp", 885)
+        || mdns_test_service_add("_airport", "_tcp", 885)
+        || mdns_test_service_add("_printer", "_tcp", 885)
+        || mdns_test_service_add("_airplay", "_tcp", 885)
+        || mdns_test_service_add("_raop", "_tcp", 885)
+        || mdns_test_service_add("_uscan", "_tcp", 885)
+        || mdns_test_service_add("_uscans", "_tcp", 885)
+        || mdns_test_service_add("_ippusb", "_tcp", 885)
+        || mdns_test_service_add("_scanner", "_tcp", 885)
+        || mdns_test_service_add("_ipp", "_tcp", 885)
+        || mdns_test_service_add("_ipps", "_tcp", 885)
+        || mdns_test_service_add("_pdl-datastream", "_tcp", 885)
+        || mdns_test_service_add("_ptp", "_tcp", 885)
+        || mdns_test_service_add("_sleep-proxy", "_udp", 885))
     {
-        abort();
+        abort(); 
+    }
+        
+    mdns_result_t * results = NULL;
+    FILE *file;
+    size_t nread;
+
+#ifdef INSTR_IS_OFF
+    size_t len = 1460;
+    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;
+    }
+    else
+    {
+        //
+        // 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);
     }
 
+    for (i=0; i<1; i++) {
+#else
     while (__AFL_LOOP(1000)) {
         memset(buf, 0, 1460);
         size_t len = read(0, buf, 1460);
-        mdns_query(mdns, "_afpovertcp", "_tcp", 0);
-        mdns_parse_packet(mdns, buf, len);
-        mdns_query_end(mdns);
+#endif
+        mypbuf.payload = buf;
+        mypbuf.len = len;
+        g_packet.pb = &mypbuf;
+        mdns_test_query("_afpovertcp", "_tcp");
+        mdns_parse_packet(&g_packet);
     }
+    ForceTaskDelete();
+    mdns_free();
     return 0;
 }
-
-#endif