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
// 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);
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;
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;
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
*/
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);
}
/**
*/
static esp_err_t _mdns_service_task_start()
{
-#ifndef MDNS_TEST_MODE
if (!_mdns_service_semaphore) {
_mdns_service_semaphore = xSemaphoreCreateMutex();
if (!_mdns_service_semaphore) {
}
}
MDNS_SERVICE_UNLOCK();
-#endif
-
return ESP_OK;
}
*/
static esp_err_t _mdns_service_task_stop()
{
-#ifndef MDNS_TEST_MODE
MDNS_SERVICE_LOCK();
_mdns_stop_timer();
if (_mdns_service_task_handle) {
}
}
MDNS_SERVICE_UNLOCK();
-#endif
return ESP_OK;
}
--- /dev/null
+
+/*
+ * 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;
+}
--- /dev/null
+#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_ */
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)
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)
#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
#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 */
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;
};
};
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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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
// 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