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
This commit is contained in:
David Cermak 2019-03-11 11:49:29 +01:00
parent 288bc2bfca
commit 10b4ddb467

View file

@ -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
*/