mdns: Allow TXT entries larger than 63 bytes; add configurable maximum TXT RDATA length

This commit is contained in:
2026-01-01 21:05:26 -07:00
parent dfc2efe117
commit a8aa758153
5 changed files with 41 additions and 10 deletions

View File

@@ -92,9 +92,9 @@ If this call returns successfully, the following queries will be answered:
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
}
Since a hostname struct is used for TXT storage each single item can be max
63 bytes long, and the total max length (including length bytes for each
item) is 255 bytes.
Each item is encoded as a length byte followed by the data, so each single
item can be max 255 bytes long, and the total max length (including length
bytes for each item) is defined by MDNS_TXT_RDATA_MAXLEN (default 255).
If your device runs a webserver on port 80, an example call might be:

View File

@@ -1272,7 +1272,7 @@ mdns_parse_pkt_known_answers(struct netif *netif, struct mdns_packet *pkt,
} else if (match & REPLY_SERVICE_TXT) {
mdns_prepare_txtdata(service);
if (service->txtdata.length == ans.rd_length &&
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.rdata, ans.rd_length) == 0) {
LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n"));
reply->serv_replies[i] &= ~REPLY_SERVICE_TXT;
}
@@ -2050,7 +2050,7 @@ mdns_handle_response(struct mdns_packet *pkt, struct netif *netif)
} else if (ans.info.type == DNS_RRTYPE_TXT) {
mdns_prepare_txtdata(service);
if (service->txtdata.length == ans.rd_length &&
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.rdata, ans.rd_length) == 0) {
LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own TXT record -> no conflict\n"));
conflict = 0;
}
@@ -2613,10 +2613,29 @@ mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name)
return ERR_OK;
}
/* Adds an RFC 1035 character-string to TXT RDATA. */
static err_t
mdns_txt_add_charstr(struct mdns_txtdata *txtdata, const char *value, u8_t len)
{
if (1 + len + txtdata->length > MDNS_TXT_RDATA_MAXLEN) {
LWIP_DEBUGF(MDNS_DEBUG, ("mdns_txt_add_charstr: adding string would exceed buffer (1+%d+%d > %d). Consider increasing MDNS_TXT_RDATA_MAXLEN.\n",
len, txtdata->length, MDNS_TXT_RDATA_MAXLEN));
return ERR_MEM;
}
txtdata->rdata[txtdata->length] = len;
txtdata->length++;
if (len) {
MEMCPY(&txtdata->rdata[txtdata->length], value, len);
txtdata->length += len;
}
return ERR_OK;
}
/**
* @ingroup mdns
* Call this function from inside the service_get_txt_fn_t callback to add text data.
* Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte.
* Buffer for TXT data is MDNS_TXT_RDATA_MAXLEN (default 256) bytes, and each
* field is prefixed with a length byte.
* @param service The service provided to the get_txt callback
* @param txt String to add to the TXT field.
* @param txt_len Length of string
@@ -2629,7 +2648,7 @@ mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_
LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
/* Use a mdns_domain struct to store txt chunks since it is the same encoding */
return mdns_domain_add_label(&service->txtdata, txt, txt_len);
return mdns_txt_add_charstr(&service->txtdata, txt, txt_len);
}
#if LWIP_MDNS_SEARCH

View File

@@ -62,7 +62,7 @@ static void mdns_clear_outmsg(struct mdns_outmsg *outmsg);
void
mdns_prepare_txtdata(struct mdns_service *service)
{
memset(&service->txtdata, 0, sizeof(struct mdns_domain));
memset(&service->txtdata, 0, sizeof(struct mdns_txtdata));
if (service->txt_fn) {
service->txt_fn(service, service->txt_userdata);
}
@@ -508,7 +508,7 @@ mdns_add_txt_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
}
LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n"));
return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN,
msg->cache_flush, ttl, (u8_t *) &service->txtdata.name,
msg->cache_flush, ttl, service->txtdata.rdata,
service->txtdata.length, NULL);
}

View File

@@ -88,6 +88,12 @@
#define MDNS_OUTPUT_PACKET_SIZE ((MDNS_MAX_SERVICES == 1) ? 512 : 1450)
#endif
/** The maximum size of TXT RDATA allocated for each service record.
*/
#ifndef MDNS_TXT_RDATA_MAXLEN
# define MDNS_TXT_RDATA_MAXLEN 256
#endif
/** MDNS_RESP_USENETIF_EXTCALLBACK==1: register an ext_callback on the netif
* to automatically restart probing/announcing on status or address change.
*/

View File

@@ -90,10 +90,16 @@ struct mdns_request {
};
#endif
/** TXT record data */
struct mdns_txtdata {
u8_t rdata[MDNS_TXT_RDATA_MAXLEN];
u16_t length;
};
/** Description of a service */
struct mdns_service {
/** TXT record to answer with */
struct mdns_domain txtdata;
struct mdns_txtdata txtdata;
/** Name of service, like 'myweb' */
char name[MDNS_LABEL_MAXLEN + 1];
/** Type of service, like '_http' */