Эх сурвалжийг харах

Merge branch 'bugfix/mdns_query_id' into 'master'

mdns: Responding: Fix query ID, add questions if not strict mode

Closes IDFGH-3639 and IDFGH-3577

See merge request espressif/esp-idf!9795
David Čermák 5 жил өмнө
parent
commit
9e8f4e51b2

+ 14 - 0
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;
 

+ 18 - 0
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 {

+ 1 - 0
examples/common_components/protocol_examples_common/connect.c

@@ -207,6 +207,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;
 }
 

+ 10 - 3
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()