diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 711de2a451..debc026511 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) { @@ -1311,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; @@ -2662,6 +2675,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 f572cc2330..b4ad03df49 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 @@ -236,6 +252,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 +321,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 { diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 9713edda2c..ceddf97d20 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -105,6 +105,7 @@ esp_err_t example_disconnect(void) stop(); ESP_LOGI(TAG, "Disconnected from %s", s_connection_name); s_connection_name = NULL; + ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop)); return ESP_OK; } diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index af897bb799..61bcae9d81 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()