From faef936581924908b1add2d3db923eb57d604725 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 27 Jul 2020 07:14:34 +0200 Subject: [PATCH 1/4] mdns: Fix include query ID in reponses Closes https://github.com/espressif/esp-idf/issues/5574 --- components/mdns/mdns.c | 3 +++ components/mdns/private_include/mdns_private.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 711de2a451..750456c7ea 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -980,6 +980,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) uint8_t count; _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); + _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); count = 0; q = p->questions; @@ -1259,6 +1260,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed } packet->flags = MDNS_FLAGS_AUTHORITATIVE; packet->distributed = parsed_packet->distributed; + packet->id = parsed_packet->id; mdns_parsed_question_t * q = parsed_packet->questions; while (q) { @@ -2662,6 +2664,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->multicast = packet->multicast; parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE; parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED; + parsed_packet->id = header.id; ip_addr_copy(parsed_packet->src, packet->src); parsed_packet->src_port = packet->src_port; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 535c25f6b5..f14619f060 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -236,6 +236,7 @@ typedef struct { uint8_t distributed; mdns_parsed_question_t * questions; mdns_parsed_record_t * records; + uint16_t id; } mdns_parsed_packet_t; typedef struct { @@ -304,6 +305,7 @@ typedef struct mdns_tx_packet_s { mdns_out_answer_t * servers; mdns_out_answer_t * additional; bool queued; + uint16_t id; } mdns_tx_packet_t; typedef struct { From e1e481f438832352322701c0d96715e212ef1daf Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 28 Jul 2020 09:06:12 +0200 Subject: [PATCH 2/4] mdns: Support queries in responses in mDNS non-strict mode By default adds original queries to responses in order to be resolved by some resolvers, such as lwIP mdns library. This functionality however is discouraged by the RFC6762, so it could be disabled in menuconfig if MDNS_STRICT_MODE configured Closes https://github.com/espressif/esp-idf/issues/5521 --- components/mdns/mdns.c | 11 +++++++++++ components/mdns/private_include/mdns_private.h | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 750456c7ea..debc026511 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1313,6 +1313,17 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed _mdns_free_tx_packet(packet); return; } +#ifdef MDNS_REPEAT_QUERY_IN_RESPONSE + mdns_out_question_t * out_question = malloc(sizeof(mdns_out_question_t)); + if (out_question == NULL) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return; + } + memcpy(out_question, q, sizeof(mdns_out_question_t)); + out_question->next = NULL; + queueToEnd(mdns_out_question_t, packet->questions, out_question); +#endif // MDNS_REPEAT_QUERY_IN_RESPONSE } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, send_flush, false)) { _mdns_free_tx_packet(packet); return; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index f14619f060..3fa57e597e 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -23,6 +23,22 @@ #define _mdns_dbg_printf(...) printf(__VA_ARGS__) #endif +/** mDNS strict mode: Set this to 1 for the mDNS library to strictly follow the RFC6762: + * Strict features: + * - to do not set original questions in response packets per RFC6762, sec 6 + * + * The actual configuration is 0, i.e. non-strict mode, since some implementations, + * such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) + * could not correctly resolve advertised names. + */ +#define MDNS_STRICT_MODE 0 + +#if !MDNS_STRICT_MODE +/* mDNS responders sometimes repeat queries in responses + * but according to RFC6762, sec 6: Responses MUST NOT contain + * any item in question field */ +#define MDNS_REPEAT_QUERY_IN_RESPONSE 1 +#endif /** The maximum number of services */ #define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES From 05211963ee5fbac0c1335286da7f2eab673aaa86 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 29 Jul 2020 10:18:34 +0200 Subject: [PATCH 3/4] examples: Common connect component: Unregister shutdown handler on disconnection To be able to connect smoothly after disconnecting, we have to unregister all handlers including shutdown handler on disconnection --- examples/common_components/protocol_examples_common/connect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index ed502210c8..e1d4d220a2 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -196,6 +196,7 @@ esp_err_t example_disconnect(void) vSemaphoreDelete(s_semph_get_ip_addrs); s_semph_get_ip_addrs = NULL; stop(); + ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop)); return ESP_OK; } From e95f97d40ef427b72a84019b632893eb555277a6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 30 Jul 2020 16:12:37 +0200 Subject: [PATCH 4/4] mdns test: Add test to resolve esp32 hostname with DiG --- examples/protocols/mdns/mdns_example_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index acd29ae725..2acf458853 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -6,12 +6,11 @@ import struct import dpkt import dpkt.dns from threading import Thread, Event +import subprocess from tiny_test_fw import DUT import ttfw_idf -# g_run_server = True -# g_done = False stop_mdns_server = Event() esp_answered = Event() @@ -112,7 +111,8 @@ def test_examples_protocol_mdns(env, extra_data): thread1 = Thread(target=mdns_server, args=(specific_host,)) thread1.start() try: - dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)[0] + print("Connected to AP with IP: {}".format(ip_address)) except DUT.ExpectTimeout: stop_mdns_server.set() thread1.join() @@ -125,6 +125,13 @@ def test_examples_protocol_mdns(env, extra_data): dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) + # 5. check the DUT answers to `dig` command + dig_output = subprocess.check_output(['dig', '+short', '-p', '5353', '@224.0.0.251', + '{}.local'.format(specific_host)]) + print('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output)) + if not ip_address.encode('utf-8') in dig_output: + raise ValueError("Test has failed: Incorrectly resolved DUT hostname using dig" + "Output should've contained DUT's IP address:{}".format(ip_address)) finally: stop_mdns_server.set() thread1.join()