From 10b4ddb467b54ad9c3f7f7a778c6328dd11f683f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 11 Mar 2019 11:49:29 +0100 Subject: [PATCH] mdns: fix possible crash when probing on particular interface with duplicated service instances due to naming conflicts on network Issue: MDNS server initially sends probing packets to resolve naming confilicts with already registered service instances. In case of a conflict, instance name is altered and probing restarts. Original instance however wasnnot removed from the structure and upon service removal only one entry was removed and a dangling service might have been kept in the structure to bring about a crash. Resolution: Keep only one instance of a service in the probing structure. Closes IDF-438 --- components/mdns/mdns.c | 55 +++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index b3a38b65b..6df429fc9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1452,20 +1452,13 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i } /** - * @brief Send probe for particular services on particular PCB + * @brief Send probe for additional services on particular PCB */ -static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +static void _mdns_init_pcb_probe_new_service(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) { mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; size_t services_final_len = len; - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - - if (_str_null_or_empty(_mdns_server->hostname)) { - pcb->state = PCB_RUNNING; - return; - } - if (PCB_STATE_IS_PROBING(pcb)) { services_final_len += pcb->probe_services_len; } @@ -1510,6 +1503,50 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t pcb->state = PCB_PROBE_1; } +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +{ + mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + + if (_str_null_or_empty(_mdns_server->hostname)) { + pcb->state = PCB_RUNNING; + return; + } + + if (PCB_STATE_IS_PROBING(pcb)) { + // Looking for already probing services to resolve duplications + mdns_srv_item_t * new_probe_services[len]; + int new_probe_service_len = 0; + bool found; + for (int j=0; j < len; ++j) { + found = false; + for (int i=0; i < pcb->probe_services_len; ++i) { + if (pcb->probe_services[i] == services[j]) { + found = true; + break; + } + } + if (!found) { + new_probe_services[new_probe_service_len++] = services[j]; + } + } + // init probing for newly added services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, + new_probe_service_len?new_probe_services:NULL, new_probe_service_len, probe_ip); + } else { + // not probing, so init for all services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); + } +} + /** * @brief Restart the responder on particular PCB */