MDNS-Fuzzer: AFL fuzzer tests for mdsn packet parser

This commit is contained in:
David Cermak 2018-05-04 16:42:54 +02:00 committed by David Cermak
parent b827e0e331
commit e983230be9
10 changed files with 833 additions and 391 deletions

View File

@ -18,12 +18,8 @@
extern "C" { extern "C" {
#endif #endif
#ifndef MDNS_TEST_MODE
#include <tcpip_adapter.h> #include <tcpip_adapter.h>
#include "esp_event.h" #include "esp_event.h"
#else
#include "esp32_compat.h"
#endif
#define MDNS_TYPE_A 0x0001 #define MDNS_TYPE_A 0x0001
#define MDNS_TYPE_PTR 0x000C #define MDNS_TYPE_PTR 0x000C

View File

@ -11,25 +11,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "mdns.h" #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_private.h" #include "mdns_private.h"
#include "mdns_networking.h"
#include <string.h>
#ifdef MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG
void mdns_debug_packet(const uint8_t * data, size_t len); 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_DEFAULT_DOMAIN = "local";
static const char * MDNS_SUB_STR = "_sub"; 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 volatile TaskHandle_t _mdns_service_task_handle = NULL;
static SemaphoreHandle_t _mdns_service_semaphore = 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; return NULL;
} }
/* esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
* MDNS Server Networking
* */
/**
* @brief Queue RX packet action
*/
static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
{ {
mdns_action_t * action = NULL; 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; 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 * @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); mdns_debug_packet(packet, index);
#endif #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() static esp_err_t _mdns_service_task_start()
{ {
#ifndef MDNS_TEST_MODE
if (!_mdns_service_semaphore) { if (!_mdns_service_semaphore) {
_mdns_service_semaphore = xSemaphoreCreateMutex(); _mdns_service_semaphore = xSemaphoreCreateMutex();
if (!_mdns_service_semaphore) { if (!_mdns_service_semaphore) {
@ -4212,8 +3910,6 @@ static esp_err_t _mdns_service_task_start()
} }
} }
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
#endif
return ESP_OK; return ESP_OK;
} }
@ -4225,7 +3921,6 @@ static esp_err_t _mdns_service_task_start()
*/ */
static esp_err_t _mdns_service_task_stop() static esp_err_t _mdns_service_task_stop()
{ {
#ifndef MDNS_TEST_MODE
MDNS_SERVICE_LOCK(); MDNS_SERVICE_LOCK();
_mdns_stop_timer(); _mdns_stop_timer();
if (_mdns_service_task_handle) { if (_mdns_service_task_handle) {
@ -4241,7 +3936,6 @@ static esp_err_t _mdns_service_task_stop()
} }
} }
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
#endif
return ESP_OK; return ESP_OK;
} }

View File

@ -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;
}

View File

@ -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_ */

View File

@ -1,17 +1,25 @@
TEST_NAME=test TEST_NAME=test
FUZZ=afl-fuzz 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) CPP=$(CC)
LD=$(CC) LD=$(CC)
OBJECTS=mdns.o test.o OBJECTS=mdns.o esp32_mock.o test.o
CFLAGS=-DMDNS_TEST_MODE -I. -I../include
OS := $(shell uname) OS := $(shell uname)
ifeq ($(OS),Darwin) ifeq ($(OS),Darwin)
LDLIBS= LDLIBS=
else else
LDLIBS=-lbsd LDLIBS=-lbsd
CFLAGS+=-DUSE_BSD_STRING CFLAGS+=-DUSE_BSD_STRING
endif endif
all: $(TEST_NAME) all: $(TEST_NAME)
@ -22,11 +30,11 @@ all: $(TEST_NAME)
mdns.o: ../mdns.c mdns.o: ../mdns.c
@echo "[CC] $<" @echo "[CC] $<"
@$(CC) $(CFLAGS) -c $< -o $@ @$(CC) $(CFLAGS) $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@
$(TEST_NAME): $(OBJECTS) $(TEST_NAME): $(OBJECTS)
@echo "[LD] $@" @echo "[LD] $@"
@$(LD) $(LDLIBS) $(OBJECTS) -o $@ @$(LD) $(OBJECTS) -o $@ $(LDLIBS)
fuzz: $(TEST_NAME) fuzz: $(TEST_NAME)
@$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME)

View File

@ -17,6 +17,12 @@
#ifdef MDNS_TEST_MODE #ifdef MDNS_TEST_MODE
// Not to include
#define ESP_MDNS_NETWORKING_H_
#define _TCPIP_ADAPTER_H_
#define __ESP_EVENT_H__
#ifdef USE_BSD_STRING #ifdef USE_BSD_STRING
#include <bsd/string.h> #include <bsd/string.h>
#endif #endif
@ -28,6 +34,7 @@
#include <signal.h> #include <signal.h>
#include <sys/time.h> #include <sys/time.h>
#define ERR_OK 0 #define ERR_OK 0
#define ESP_OK 0 #define ESP_OK 0
#define ESP_FAIL -1 #define ESP_FAIL -1
@ -44,21 +51,26 @@
#define pdTRUE true #define pdTRUE true
#define pdFALSE false #define pdFALSE false
#define pdPASS ( pdTRUE )
#define pdFAIL ( pdFALSE )
#define portMAX_DELAY 0xFFFFFFFF #define portMAX_DELAY 0xFFFFFFFF
#define portTICK_PERIOD_MS 1 #define portTICK_PERIOD_MS 1
#define xSemaphoreTake(s,d) #define xSemaphoreTake(s,d)
#define xTaskDelete(a)
#define vTaskDelete(a) free(a)
#define xSemaphoreGive(s) #define xSemaphoreGive(s)
#define _mdns_pcb_init(a,b) true
#define _mdns_pcb_deinit(a,b) true
#define xSemaphoreCreateMutex() malloc(1) #define xSemaphoreCreateMutex() malloc(1)
#define vSemaphoreDelete(s) free(s) #define vSemaphoreDelete(s) free(s)
#define xQueueCreate(n,s) malloc((n)*(s)) #define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1)
#define vQueueDelete(q) free(q) #define vTaskDelay(m) usleep((m)*0)
#define xQueueReceive(q, d, t) (ESP_OK)
#define vTaskDelay(m) usleep((m)*1000)
#define pbuf_free(p) free(p) #define pbuf_free(p) free(p)
#define esp_random() (rand()%UINT32_MAX)
#define tcpip_adapter_get_ip_info(i,d) #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_ip6_linklocal(i,d) (ESP_OK)
#define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB" #define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB"
@ -67,17 +79,31 @@
((uint32_t)((c) & 0xff) << 16) | \ ((uint32_t)((c) & 0xff) << 16) | \
((uint32_t)((b) & 0xff) << 8) | \ ((uint32_t)((b) & 0xff) << 8) | \
(uint32_t)((a) & 0xff) (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 int32_t esp_err_t;
typedef void * xSemaphoreHandle; typedef void * xSemaphoreHandle;
typedef void * SemaphoreHandle_t;
typedef void * xQueueHandle; 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 { typedef enum {
WIFI_MODE_NULL = 0, /**< null mode */ WIFI_MODE_NULL = 0, /**< null mode */
@ -87,6 +113,42 @@ typedef enum {
WIFI_MODE_MAX WIFI_MODE_MAX
} wifi_mode_t; } 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 { struct udp_pcb {
uint8_t dummy; uint8_t dummy;
}; };
@ -101,27 +163,76 @@ struct ip6_addr {
}; };
typedef struct ip6_addr ip6_addr_t; 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 { typedef struct {
ip4_addr_t ip; ip4_addr_t ip;
ip4_addr_t netmask; ip4_addr_t netmask;
ip4_addr_t gw; ip4_addr_t gw;
} tcpip_adapter_ip_info_t; } 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) inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode)
{ {
*mode = WIFI_MODE_APSTA; *mode = WIFI_MODE_APSTA;
return ESP_OK; return ESP_OK;
} }
inline uint32_t xTaskGetTickCount() struct pbuf {
{ struct pbuf *next;
struct timeval tv; void *payload;
struct timezone tz; uint16_t tot_len;
if (gettimeofday(&tv, &tz) == 0) { uint16_t len;
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); uint8_t /*pbuf_type*/ type;
} uint8_t flags;
return 0; 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 #endif //MDNS_TEST_MODE

View File

@ -0,0 +1,84 @@
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "esp32_compat.h"
void* g_queue;
int g_queue_send_shall_fail = 0;
int g_size = 0;
esp_err_t esp_timer_delete(esp_timer_handle_t timer)
{
return ESP_OK;
}
esp_err_t esp_timer_stop(esp_timer_handle_t timer)
{
return ESP_OK;
}
esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period)
{
return ESP_OK;
}
esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
esp_timer_handle_t* out_handle)
{
return ESP_OK;
}
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;
}
/// Queue mock
QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize )
{
g_size = uxItemSize;
g_queue = malloc((uxQueueLength)*(uxItemSize));
return g_queue;
}
void vQueueDelete( QueueHandle_t xQueue )
{
free(xQueue);
}
uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait)
{
if (g_queue_send_shall_fail)
{
return pdFALSE;
}
else
{
memcpy(xQueue, pvItemToQueue, g_size);
return pdPASS;
}
}
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
{
return pdFALSE;
}
void GetLastItem(void *pvBuffer)
{
memcpy(pvBuffer, g_queue, g_size);
}
void ForceTaskDelete()
{
g_queue_send_shall_fail = 1;
}

View File

@ -0,0 +1,45 @@
#ifndef ESP32_MOCK_H_
#define ESP32_MOCK_H_
typedef void (*esp_timer_cb_t)(void* arg);
typedef enum
{
ESP_TIMER_TASK, //!< Callback is called from timer task
} esp_timer_dispatch_t;
typedef struct
{
esp_timer_cb_t callback; //!< Function to call when timer expires
void* arg; //!< Argument to pass to the callback
esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR
const char* name; //!< Timer name, used in esp_timer_dump function
} esp_timer_create_args_t;
esp_err_t esp_timer_delete(esp_timer_handle_t timer);
esp_err_t esp_timer_stop(esp_timer_handle_t timer);
esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period);
esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
esp_timer_handle_t* out_handle);
// Queue mock
QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
uint32_t uxItemSize );
void vQueueDelete( QueueHandle_t xQueue );
uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
void GetLastItem(void *pvBuffer);
void ForceTaskDelete();
#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len
#endif /* ESP32_MOCK_H_ */

View File

@ -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);
}

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifdef MDNS_TEST_MODE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -21,93 +19,210 @@
#include <string.h> #include <string.h>
#include "mdns.h" #include "mdns.h"
#include "mdns_private.h"
void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); //
// 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;
}
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 main(int argc, char** argv)
{ {
int i;
const char * mdns_hostname = "minifritz"; const char * mdns_hostname = "minifritz";
const char * mdns_instance = "Hristo's Time Capsule"; const char * mdns_instance = "Hristo's Time Capsule";
const char * arduTxtData[4] = { mdns_txt_item_t arduTxtData[4] = {
"board=esp32", {"board","esp32"},
"tcp_check=no", {"tcp_check","no"},
"ssh_upload=no", {"ssh_upload","no"},
"auth_upload=no" {"auth_upload","no"}
}; };
const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32};
mdns_server_t * mdns = NULL;
uint8_t buf[1460]; uint8_t buf[1460];
char winstance[21+strlen(mdns_hostname)]; 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]); 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)) { // Init depencency injected methods
mdns_test_init_di();
if (mdns_init()) {
abort(); abort();
} }
if (mdns_set_hostname(mdns, mdns_hostname)) { if (mdns_test_hostname_set(mdns_hostname)) {
abort(); abort();
} }
if (mdns_set_instance(mdns, mdns_instance)) { if (mdns_test_service_add("_workstation", "_tcp", 9)) {
abort();
}
if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) {
abort(); abort();
} }
if (mdns_service_add(mdns, "_workstation", "_tcp", 9)) { if (mdns_test_service_add("_arduino", "_tcp", 3232)) {
abort(); abort();
} }
if (mdns_service_instance_set(mdns, "_workstation", "_tcp", winstance)) { if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) {
abort(); abort();
} }
if (mdns_service_add(mdns, "_arduino", "_tcp", 3232)) { if (mdns_test_service_add("_http", "_tcp", 80)) {
abort(); abort();
} }
if (mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData)) { if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) {
abort();
}
if (mdns_service_add(mdns, "_http", "_tcp", 80)) {
abort();
}
if (mdns_service_instance_set(mdns, "_http", "_tcp", "ESP WebServer")) {
abort(); abort();
} }
if ( if (
mdns_service_add(mdns, "_afpovertcp", "_tcp", 548) mdns_test_service_add("_afpovertcp", "_tcp", 548)
|| mdns_service_add(mdns, "_rfb", "_tcp", 885) || mdns_test_service_add("_rfb", "_tcp", 885)
|| mdns_service_add(mdns, "_smb", "_tcp", 885) || mdns_test_service_add("_smb", "_tcp", 885)
|| mdns_service_add(mdns, "_adisk", "_tcp", 885) || mdns_test_service_add("_adisk", "_tcp", 885)
|| mdns_service_add(mdns, "_airport", "_tcp", 885) || mdns_test_service_add("_airport", "_tcp", 885)
|| mdns_service_add(mdns, "_printer", "_tcp", 885) || mdns_test_service_add("_printer", "_tcp", 885)
|| mdns_service_add(mdns, "_airplay", "_tcp", 885) || mdns_test_service_add("_airplay", "_tcp", 885)
|| mdns_service_add(mdns, "_raop", "_tcp", 885) || mdns_test_service_add("_raop", "_tcp", 885)
|| mdns_service_add(mdns, "_uscan", "_tcp", 885) || mdns_test_service_add("_uscan", "_tcp", 885)
|| mdns_service_add(mdns, "_uscans", "_tcp", 885) || mdns_test_service_add("_uscans", "_tcp", 885)
|| mdns_service_add(mdns, "_ippusb", "_tcp", 885) || mdns_test_service_add("_ippusb", "_tcp", 885)
|| mdns_service_add(mdns, "_scanner", "_tcp", 885) || mdns_test_service_add("_scanner", "_tcp", 885)
|| mdns_service_add(mdns, "_ipp", "_tcp", 885) || mdns_test_service_add("_ipp", "_tcp", 885)
|| mdns_service_add(mdns, "_ipps", "_tcp", 885) || mdns_test_service_add("_ipps", "_tcp", 885)
|| mdns_service_add(mdns, "_pdl-datastream", "_tcp", 885) || mdns_test_service_add("_pdl-datastream", "_tcp", 885)
|| mdns_service_add(mdns, "_ptp", "_tcp", 885) || mdns_test_service_add("_ptp", "_tcp", 885)
|| mdns_service_add(mdns, "_sleep-proxy", "_udp", 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)) { while (__AFL_LOOP(1000)) {
memset(buf, 0, 1460); memset(buf, 0, 1460);
size_t len = read(0, buf, 1460); size_t len = read(0, buf, 1460);
mdns_query(mdns, "_afpovertcp", "_tcp", 0); #endif
mdns_parse_packet(mdns, buf, len); mypbuf.payload = buf;
mdns_query_end(mdns); mypbuf.len = len;
g_packet.pb = &mypbuf;
mdns_test_query("_afpovertcp", "_tcp");
mdns_parse_packet(&g_packet);
} }
ForceTaskDelete();
mdns_free();
return 0; return 0;
} }
#endif