Skip to content

Commit 91134f1

Browse files
committed
mdns: Make reverse query conditional per Kconfig
and auto-register reverse logical names
1 parent fb8a2f0 commit 91134f1

File tree

12 files changed

+160
-125
lines changed

12 files changed

+160
-125
lines changed

.github/workflows/host-test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,7 @@ jobs:
5757
. ${IDF_PATH}/export.sh
5858
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
5959
idf.py build
60-
./build/mdns_host.elf & dig +short -p 5353 @224.0.0.251 myesp.local
60+
./build/mdns_host.elf &
61+
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
62+
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
63+
cat ip.txt

components/mdns/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ menu "mDNS"
9595
help
9696
Enable for the library to log received and sent mDNS packets to stdout.
9797

98+
config MDNS_RESPOND_REVERSE_QUERIES
99+
bool "Enable responding to IPv4 reverse queries"
100+
default n
101+
help
102+
Enables support for IPv4 reverse lookup. If enabled, the mDNS library
103+
response to PTR queries of "A.B.C.D.in-addr.arpa" type.
104+
98105
config MDNS_MULTIPLE_INSTANCE
99106
bool "Multiple instances under the same service type"
100107
default y

components/mdns/examples/main/mdns_example_main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Unlicense OR CC0-1.0
55
*/
@@ -279,6 +279,13 @@ void app_main(void)
279279
ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4));
280280
ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4));
281281
#endif
282+
283+
#if defined(CONFIG_MDNS_RESPOND_REVERSE_QUERIES)
284+
while (mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_IP4_REVERSE_LOOKUP) != ESP_OK) {
285+
vTaskDelay(50 / portTICK_PERIOD_MS);
286+
}
287+
#endif
288+
282289
initialise_button();
283290
xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL);
284291
}

components/mdns/include/mdns.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ typedef enum {
3434
MDNS_EVENT_ANNOUNCE_IP6 = 1 << 4,
3535
MDNS_EVENT_DISABLE_IP4 = 1 << 5,
3636
MDNS_EVENT_DISABLE_IP6 = 1 << 6,
37+
MDNS_EVENT_IP4_REVERSE_LOOKUP = 1 << 7,
38+
MDNS_EVENT_IP6_REVERSE_LOOKUP = 1 << 8,
3739
} mdns_event_actions_t;
3840

3941
/**

components/mdns/mdns.c

Lines changed: 118 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
#include "mdns_networking.h"
1818
#include "esp_log.h"
1919
#include "esp_random.h"
20-
#if __has_include("bsd/string.h")
21-
#include "bsd/string.h"
22-
#endif
20+
2321
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
2422
#include "esp_eth.h"
2523
#endif
@@ -439,7 +437,11 @@ static const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *star
439437
if (name->parts == 1 && buf[0] != '_'
440438
&& (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0)
441439
&& (strcasecmp(buf, "arpa") != 0)
442-
&& (strcasecmp(buf, "ip6") != 0)) {
440+
&& (strcasecmp(buf, "ip6") != 0)
441+
#ifndef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
442+
&& (strcasecmp(buf, "in-addr") != 0)
443+
#endif
444+
) {
443445
strlcat(name->host, ".", sizeof(name->host));
444446
strlcat(name->host, buf, sizeof(name->host));
445447
} else if (strcasecmp(buf, MDNS_SUB_STR) == 0) {
@@ -643,6 +645,60 @@ static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index,
643645
return len + 1;
644646
}
645647

648+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
649+
static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len)
650+
{
651+
if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) {
652+
return 0;
653+
}
654+
if (!_mdns_append_u8(packet, index, len)) {
655+
return 0;
656+
}
657+
memcpy(packet + *index, str, len);
658+
*index += len;
659+
return *index;
660+
}
661+
662+
/**
663+
* @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as
664+
* _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items),
665+
* where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses)
666+
*
667+
* @param packet MDNS packet
668+
* @param index offset in the packet
669+
* @param name name representing FQDN in '.' separated parts
670+
* @param last true if appending the last part (domain, typically "arpa")
671+
*
672+
* @return length of added data: 0 on error or length on success
673+
*/
674+
static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *name, bool last)
675+
{
676+
int len = strlen(name);
677+
char *host = (char *)name;
678+
char *end = host;
679+
char *start = host;
680+
do {
681+
end = memchr(start, '.', len);
682+
end = end ? end : host + len;
683+
int part_len = end - start;
684+
if (!append_single_str(packet, index, start, part_len)) {
685+
return 0;
686+
}
687+
start = ++end;
688+
} while (end < name + len);
689+
690+
if (!append_single_str(packet, index, "arpa", sizeof("arpa") - 1)) {
691+
return 0;
692+
}
693+
694+
//empty string so terminate
695+
if (!_mdns_append_u8(packet, index, 0)) {
696+
return 0;
697+
}
698+
return *index;
699+
}
700+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
701+
646702
/**
647703
* @brief appends FQDN to a packet, incrementing the index and
648704
* compressing the output if previous occurrence of the string (or part of it) has been found
@@ -1104,21 +1160,18 @@ static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const
11041160
*/
11051161
static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q)
11061162
{
1107-
const char *str[6];
1108-
uint8_t str_index = 0;
11091163
uint8_t part_length;
1110-
char *host_dup = NULL; // need to duplicate host-name for some cases
1164+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
11111165
if (q->host && strstr(q->host, "in-addr")) {
1112-
host_dup = strdup(q->host);
1113-
char *rest = NULL;
1114-
for (char *p = strtok_r(host_dup, ".", &rest); p != NULL; p = strtok_r(NULL, ".", &rest)) {
1115-
str[str_index++] = p;
1116-
}
1117-
if (q->domain) {
1118-
str[str_index++] = q->domain;
1166+
part_length = append_fqdn_dots(packet, index, q->host, false);
1167+
if (!part_length) {
1168+
return 0;
11191169
}
1120-
1121-
} else {
1170+
} else
1171+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
1172+
{
1173+
const char *str[4];
1174+
uint8_t str_index = 0;
11221175
if (q->host) {
11231176
str[str_index++] = q->host;
11241177
}
@@ -1131,19 +1184,14 @@ static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out
11311184
if (q->domain) {
11321185
str[str_index++] = q->domain;
11331186
}
1134-
1135-
}
1136-
1137-
1138-
part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE);
1139-
if (!part_length) {
1140-
free(host_dup);
1141-
return 0;
1187+
part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE);
1188+
if (!part_length) {
1189+
return 0;
1190+
}
11421191
}
11431192

11441193
part_length += _mdns_append_u16(packet, index, q->type);
11451194
part_length += _mdns_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001);
1146-
free(host_dup);
11471195
return part_length;
11481196
}
11491197

@@ -1221,62 +1269,36 @@ static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_h
12211269
return num_records;
12221270
}
12231271

1224-
static uint16_t _mdns_append_rev_ptr_record(uint8_t *packet, uint16_t *index, const char *name, bool flush, bool bye)
1272+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
1273+
/**
1274+
* @brief Appends reverse lookup PTR record
1275+
*/
1276+
static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name)
12251277
{
1226-
const char *str[6];
1227-
int i = 0;
1228-
12291278
if (strstr(name, "in-addr") == NULL) {
12301279
return 0;
12311280
}
1232-
char *host = strdup(name);
1233-
char *rest = NULL;
1234-
for (char *p = strtok_r(host, ".", &rest); p != NULL; p = strtok_r(NULL, ".", &rest)) {
1235-
str[i++] = p;
1236-
}
1237-
str[i++] = "arpa";
1238-
uint16_t record_length = 0;
1239-
uint8_t part_length;
12401281

1241-
part_length = _mdns_append_fqdn(packet, index, str, i, MDNS_MAX_PACKET_SIZE);
1242-
if (!part_length) {
1282+
if (!append_fqdn_dots(packet, index, name, false)) {
12431283
return 0;
12441284
}
1245-
record_length += part_length;
12461285

1247-
part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL);
1248-
if (!part_length) {
1286+
if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/ )) {
12491287
return 0;
12501288
}
1251-
record_length += part_length;
12521289

1253-
uint16_t data_len_location = *index - 2;
1254-
str[0] = _mdns_self_host.hostname;
1255-
str[1] = MDNS_DEFAULT_DOMAIN;
1290+
uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */
1291+
const char *str[2] = { _mdns_self_host.hostname, MDNS_DEFAULT_DOMAIN };
12561292

1257-
part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE);
1293+
int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE);
12581294
if (!part_length) {
12591295
return 0;
12601296
}
12611297

12621298
_mdns_set_u16(packet, data_len_location, part_length);
1263-
record_length += part_length;
1264-
1265-
return record_length;
1266-
}
1267-
1268-
1269-
static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name, bool flush, bool bye)
1270-
{
1271-
uint8_t appended_answers = 0;
1272-
1273-
if (_mdns_append_rev_ptr_record(packet, index, name, flush, bye) <= 0) {
1274-
return appended_answers;
1275-
}
1276-
appended_answers++;
1277-
1278-
return appended_answers;
1299+
return 1; /* appending only 1 record */
12791300
}
1301+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
12801302

12811303
/**
12821304
* @brief Append PTR answers to packet
@@ -1316,8 +1338,10 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an
13161338
if (answer->type == MDNS_TYPE_PTR) {
13171339
if (answer->service) {
13181340
return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye);
1341+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
13191342
} else if (answer->host && answer->host->hostname && strstr(answer->host->hostname, "in-addr")) {
1320-
return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname, answer->flush, answer->bye) > 0;
1343+
return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0;
1344+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
13211345
} else {
13221346
return _mdns_append_ptr_record(packet, index,
13231347
answer->custom_instance, answer->custom_service, answer->custom_proto,
@@ -1719,15 +1743,6 @@ static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_serv
17191743
return true;
17201744
}
17211745

1722-
static bool _mdns_create_answer_from_reverse_query(mdns_tx_packet_t *packet, const char *hostname, bool send_flush)
1723-
{
1724-
mdns_host_item_t *host = mdns_get_host_item(hostname);
1725-
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) {
1726-
return false;
1727-
}
1728-
return true;
1729-
}
1730-
17311746
static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush)
17321747
{
17331748
mdns_host_item_t *host = mdns_get_host_item(hostname);
@@ -1812,18 +1827,24 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_
18121827
_mdns_free_tx_packet(packet);
18131828
return;
18141829
}
1830+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
18151831
} else if (q->type == MDNS_TYPE_PTR) {
1816-
if (!_mdns_create_answer_from_reverse_query(packet, q->host, send_flush)) {
1817-
_mdns_free_tx_packet(packet);
1832+
mdns_host_item_t *host = mdns_get_host_item(q->host);
1833+
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) {
18181834
return;
18191835
}
1836+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
18201837
} else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) {
18211838
_mdns_free_tx_packet(packet);
18221839
return;
18231840
}
18241841

18251842
if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries"
1826-
(q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA || q->type == MDNS_TYPE_PTR)) {
1843+
(q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA
1844+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
1845+
|| q->type == MDNS_TYPE_PTR
1846+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
1847+
)) {
18271848
mdns_out_question_t *out_question = malloc(sizeof(mdns_out_question_t));
18281849
if (out_question == NULL) {
18291850
HOOK_MALLOC_FAILED;
@@ -3042,7 +3063,11 @@ static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type)
30423063
static bool _mdns_name_is_ours(mdns_name_t *name)
30433064
{
30443065
//domain have to be "local"
3045-
if (_str_null_or_empty(name->domain) || ( strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) && strcasecmp(name->domain, "arpa")) ) {
3066+
if (_str_null_or_empty(name->domain) || ( strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)
3067+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
3068+
&& strcasecmp(name->domain, "arpa")
3069+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
3070+
) ) {
30463071
return false;
30473072
}
30483073

@@ -3967,6 +3992,22 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action)
39673992
if (action & MDNS_EVENT_ANNOUNCE_IP6) {
39683993
_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true);
39693994
}
3995+
3996+
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
3997+
if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) {
3998+
esp_netif_ip_info_t if_ip_info;
3999+
if (esp_netif_get_ip_info(_mdns_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) {
4000+
esp_ip4_addr_t *ip = &if_ip_info.ip;
4001+
char *reverse_query_name = NULL;
4002+
if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr",
4003+
esp_ip4_addr4_16(ip), esp_ip4_addr3_16(ip),
4004+
esp_ip4_addr2_16(ip), esp_ip4_addr1_16(ip)) > 0 && reverse_query_name) {
4005+
ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name);
4006+
_mdns_delegate_hostname_add(reverse_query_name, NULL);
4007+
}
4008+
}
4009+
}
4010+
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
39704011
}
39714012

39724013
/**
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
idf_component_register(SRCS esp_event_mock.c
2-
INCLUDE_DIRS include
3-
REQUIRES)
2+
INCLUDE_DIRS include)

components/mdns/tests/host_test/components/esp_event/include/esp_event.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88
#include "stdbool.h"
99
#include "esp_err.h"
1010
#include "esp_event_base.h"
11-
//#include "bsd_strings.h"
12-
13-
14-
15-
//const char *WIFI_EVENT;
16-
//const char *IP_EVENT;
11+
#include "bsd/string.h"
1712

1813
esp_err_t esp_event_handler_register(const char *event_base, int32_t event_id, void *event_handler, void *event_handler_arg);
1914

components/mdns/tests/host_test/components/freertos/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp
2-
INCLUDE_DIRS include
3-
REQUIRES)
2+
INCLUDE_DIRS include)
43

54
set(THREADS_PREFER_PTHREAD_FLAG ON)
65
find_package(Threads REQUIRED)

0 commit comments

Comments
 (0)