Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/mdns__host-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,43 @@ jobs:
diff -q $file /tmp/$file || exit 1
echo "OK"
done

fuzz_test:
if: contains(github.event.pull_request.labels.*.name, 'mdns-fuzz') || github.event_name == 'push'
name: Fuzzer tests for mdns lib
strategy:
matrix:
idf_ver: ["latest"]

runs-on: ubuntu-22.04
container: aflplusplus/aflplusplus
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4

- name: Checkout ESP-IDF
uses: actions/checkout@v4
with:
repository: espressif/esp-idf
path: idf
submodules: recursive

- name: Install Necessary Libs
run: |
apt-get update -y
apt-get install -y libbsd-dev

- name: Run AFL++
shell: bash
run: |
export IDF_PATH=$GITHUB_WORKSPACE/idf
cd components/mdns/tests/test_afl_fuzz_host/
make fuzz

- name: Upload Crash Artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: fuzz-crashes
path: components/mdns/tests/test_afl_fuzz_host/out/default/crashes.tar.gz
if-no-files-found: ignore
6 changes: 6 additions & 0 deletions components/mdns/examples/simple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.22)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(simple)
2 changes: 2 additions & 0 deletions components/mdns/examples/simple/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "simple.c" "softap_example_main.c"
INCLUDE_DIRS ".")
40 changes: 40 additions & 0 deletions components/mdns/examples/simple/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
menu "Example Configuration"

config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.

config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config ESP_WIFI_CHANNEL
int "WiFi Channel"
range 1 13
default 1
help
WiFi channel (network channel) for the example to use.

config ESP_MAX_STA_CONN
int "Maximal STA connections"
default 4
help
Max number of the STA connects to AP.

config ESP_GTK_REKEYING_ENABLE
bool "Enable GTK Rekeying"
default y
help
Flag to enable GTK rekeying.

config ESP_GTK_REKEY_INTERVAL
int "GTK rekey interval"
depends on ESP_GTK_REKEYING_ENABLE
range 60 65535
default 600
help
GTK rekeying interval in seconds.
endmenu
8 changes: 8 additions & 0 deletions components/mdns/examples/simple/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dependencies:
## Required IDF version
idf: ">=5.0"
espressif/mdns:
version: "^1.0.0"
override_path: "../../../"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
167 changes: 167 additions & 0 deletions components/mdns/examples/simple/main/simple.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include "esp_netif_ip_addr.h"
#include "mdns.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"

static const char *TAG = "mdns-simple";

static void initialise_mdns(void)
{
const char *mdns_hostname = "minifritz";
const char *mdns_instance = "Hristo's Time Capsule";

mdns_txt_item_t arduTxtData[4] = {
{"board", "esp32"},
{"tcp_check", "no"},
{"ssh_upload", "no"},
{"auth_upload", "no"}
};

uint8_t mac[6];
ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_WIFI_STA));

char *winstance = NULL;
if (asprintf(&winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) < 0) {
abort();
}

ESP_ERROR_CHECK(mdns_init());
ESP_ERROR_CHECK(mdns_hostname_set(mdns_hostname));
ESP_LOGI(TAG, "mdns hostname set to: [%s]", mdns_hostname);
ESP_ERROR_CHECK(mdns_instance_name_set(mdns_instance));

// Delegate host: 17.17.17.17
mdns_ip_addr_t addr4 = { 0 };
addr4.addr.type = ESP_IPADDR_TYPE_V4;
esp_netif_str_to_ip4("17.17.17.17", &addr4.addr.u_addr.ip4);
addr4.next = NULL;
ESP_ERROR_CHECK(mdns_delegate_hostname_add(mdns_hostname, &addr4));
ESP_ERROR_CHECK(mdns_delegate_hostname_add("megafritz", &addr4));

// Services and subtypes mirroring the fuzz test setup
ESP_ERROR_CHECK(mdns_service_add(NULL, "_fritz", "_tcp", 22, NULL, 0));
ESP_ERROR_CHECK(mdns_service_subtype_add_for_host(NULL, "_fritz", "_tcp", NULL, "_server"));

ESP_ERROR_CHECK(mdns_service_add(NULL, "_telnet", "_tcp", 22, NULL, 0));

ESP_ERROR_CHECK(mdns_service_add(NULL, "_workstation", "_tcp", 9, NULL, 0));
ESP_ERROR_CHECK(mdns_service_instance_name_set("_workstation", "_tcp", winstance));

ESP_ERROR_CHECK(mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0));
ESP_ERROR_CHECK(mdns_service_txt_set("_arduino", "_tcp", arduTxtData, 4));

ESP_ERROR_CHECK(mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0));
ESP_ERROR_CHECK(mdns_service_instance_name_set("_http", "_tcp", "ESP WebServer"));

ESP_ERROR_CHECK(mdns_service_add(NULL, "_afpovertcp", "_tcp", 548, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_rfb", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_smb", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_adisk", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_airport", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_printer", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_airplay", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_raop", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_uscan", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_uscans", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_ippusb", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_scanner", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_ipp", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_ipps", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_pdl-datastream", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_ptp", "_tcp", 885, NULL, 0));
ESP_ERROR_CHECK(mdns_service_add(NULL, "_sleep-proxy", "_udp", 885, NULL, 0));

free(winstance);
}

void init_softap(void);

/* these strings match mdns_ip_protocol_t enumeration */
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};

static void mdns_print_results(mdns_result_t *results)
{
mdns_result_t *r = results;
mdns_ip_addr_t *a = NULL;
int i = 1, t;
while (r) {
if (r->esp_netif) {
printf("%d: Interface: %s, Type: %s, TTL: %" PRIu32 "\n", i++, esp_netif_get_ifkey(r->esp_netif),
ip_protocol_str[r->ip_protocol], r->ttl);
}
if (r->instance_name) {
printf(" PTR : %s.%s.%s\n", r->instance_name, r->service_type, r->proto);
}
if (r->hostname) {
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
}
if (r->txt_count) {
printf(" TXT : [%zu] ", r->txt_count);
for (t = 0; t < r->txt_count; t++) {
printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]);
}
printf("\n");
}
a = r->addr;
while (a) {
if (a->addr.type == ESP_IPADDR_TYPE_V6) {
printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6));
} else {
printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4)));
}
a = a->next;
}
r = r->next;
}
}


static void query_mdns_service(const char *service_name, const char *proto)
{
ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto);

mdns_result_t *results = NULL;
esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results);
if (err) {
ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err));
return;
}
if (!results) {
ESP_LOGW(TAG, "No results found!");
return;
}

mdns_print_results(results);
mdns_query_results_free(results);
}


void app_main(void)
{
// ESP_ERROR_CHECK(nvs_flash_init());
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());

ESP_LOGI(TAG, "mDNS Ver: %s", ESP_MDNS_VERSION_NUMBER);


// Use the common connection helper to bring up Wi‑Fi/Ethernet
init_softap();
initialise_mdns();
while (1) {
query_mdns_service("_fritz", "_tcp");

}
// ESP_ERROR_CHECK(example_connect());
}
117 changes: 117 additions & 0 deletions components/mdns/examples/simple/main/softap_example_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/* WiFi softAP Example

This example code is in the Public Domain (or CC0 licensed, at your option.)

Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"

/* The examples use WiFi configuration that you can set via project configuration menu.

If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN

#if CONFIG_ESP_GTK_REKEYING_ENABLE
#define EXAMPLE_GTK_REKEY_INTERVAL CONFIG_ESP_GTK_REKEY_INTERVAL
#else
#define EXAMPLE_GTK_REKEY_INTERVAL 0
#endif

static const char *TAG = "wifi softAP";

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d, reason=%d",
MAC2STR(event->mac), event->aid, event->reason);
}
}

void wifi_init_softap(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_ap();

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));

wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
#ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT
.authmode = WIFI_AUTH_WPA3_PSK,
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
#else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */
.authmode = WIFI_AUTH_WPA2_PSK,
#endif
.pmf_cfg = {
.required = true,
},
#ifdef CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT
.bss_max_idle_cfg = {
.period = WIFI_AP_DEFAULT_MAX_IDLE_PERIOD,
.protected_keep_alive = 1,
},
#endif
.gtk_rekey_interval = EXAMPLE_GTK_REKEY_INTERVAL,
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}

ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());

ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}

void init_softap(void)
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
wifi_init_softap();
}
6 changes: 6 additions & 0 deletions components/mdns/examples/simple/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 6.0.0 Project Minimal Configuration
#
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
CONFIG_MDNS_MAX_SERVICES=40
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
Loading
Loading