Compare commits
18 Commits
STABLE-2_2
...
mdns-big-t
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d5c99570f | |||
| c01c655c5f | |||
|
|
4599f551de | ||
|
|
41a36098b3 | ||
|
|
e7ab7e0773 | ||
|
|
b1edb7780f | ||
|
|
56b29f8bcf | ||
|
|
92522e4538 | ||
|
|
571c46253f | ||
|
|
ca0395c5ae | ||
|
|
31d8988f89 | ||
|
|
f877b457a1 | ||
|
|
6c8874bf5d | ||
|
|
8459488006 | ||
|
|
ffce5ab1c7 | ||
|
|
e55896319b | ||
|
|
ba306bcdaa | ||
|
|
554e104095 |
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }}
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
|
||||
@@ -6,6 +6,11 @@ HISTORY
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2025-06-03: Simon Goldschmidt
|
||||
* ip4_frag/ip6_frag: fix potential NULL-pointer access on memory errors
|
||||
|
||||
(STABLE-2.2.1):
|
||||
|
||||
++ New features:
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "lwIP"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "2.2.1"
|
||||
PROJECT_NUMBER = "2.2.2.dev"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -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_SIZE (default 255).
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ endif()
|
||||
|
||||
set(LWIP_VERSION_MAJOR "2")
|
||||
set(LWIP_VERSION_MINOR "2")
|
||||
set(LWIP_VERSION_REVISION "1")
|
||||
set(LWIP_VERSION_REVISION "2")
|
||||
# LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases
|
||||
# LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions
|
||||
# Numbers 1..31 are reserved for release candidates
|
||||
set(LWIP_VERSION_RC "LWIP_RC_RELEASE")
|
||||
set(LWIP_VERSION_RC "LWIP_RC_DEVELOPMENT")
|
||||
|
||||
if ("${LWIP_VERSION_RC}" STREQUAL "LWIP_RC_RELEASE")
|
||||
set(LWIP_VERSION_STRING
|
||||
|
||||
@@ -576,6 +576,10 @@ const struct altcp_functions altcp_proxyconnect_functions = {
|
||||
altcp_default_get_tcp_addrinfo,
|
||||
altcp_default_get_ip,
|
||||
altcp_default_get_port
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
, altcp_default_keepalive_disable
|
||||
, altcp_default_keepalive_enable
|
||||
#endif
|
||||
#ifdef LWIP_DEBUG
|
||||
, altcp_default_dbg_get_tcp_state
|
||||
#endif
|
||||
|
||||
@@ -120,7 +120,6 @@
|
||||
#define CRLF "\r\n"
|
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||
#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive"
|
||||
#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive"
|
||||
#endif
|
||||
|
||||
#if LWIP_HTTPD_DYNAMIC_FILE_READ
|
||||
@@ -2100,8 +2099,7 @@ http_parse_request(struct pbuf *inp, struct http_state *hs, struct altcp_pcb *pc
|
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
|
||||
/* This is HTTP/1.0 compatible: for strict 1.1, a connection
|
||||
would always be persistent unless "close" was specified. */
|
||||
if (!is_09 && (lwip_strnistr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) ||
|
||||
lwip_strnistr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) {
|
||||
if (!is_09 && lwip_strnistr(data, HTTP11_CONNECTIONKEEPALIVE, data_len)) {
|
||||
hs->keepalive = 1;
|
||||
} else {
|
||||
hs->keepalive = 0;
|
||||
|
||||
@@ -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_SIZE) {
|
||||
LWIP_DEBUGF(MDNS_DEBUG, ("mdns_txt_add_charstr: adding string would exceed buffer (1+%d+%d > %d). Consider increasing MDNS_TXT_RDATA_SIZE.\n",
|
||||
len, txtdata->length, MDNS_TXT_RDATA_SIZE));
|
||||
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_SIZE (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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -463,14 +463,8 @@ snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value
|
||||
if ((len > 0) && (len < 5)) {
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data));
|
||||
|
||||
if (data & 0x80) {
|
||||
/* negative, start from -1 */
|
||||
*value = -1;
|
||||
*value = (*value << 8) | data;
|
||||
} else {
|
||||
/* positive, start from 0 */
|
||||
*value = data;
|
||||
}
|
||||
/* sign extension */
|
||||
*value = (s8_t)data;
|
||||
len--;
|
||||
/* shift in the remaining value */
|
||||
while (len > 0) {
|
||||
|
||||
@@ -454,10 +454,12 @@ tftp_init_common(u8_t mode, const struct tftp_context *ctx)
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT);
|
||||
if (ret != ERR_OK) {
|
||||
udp_remove(pcb);
|
||||
return ret;
|
||||
if (mode & LWIP_TFTP_MODE_SERVER) {
|
||||
ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT);
|
||||
if (ret != ERR_OK) {
|
||||
udp_remove(pcb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
tftp_state.handle = NULL;
|
||||
|
||||
@@ -223,9 +223,10 @@ autoip_conflict_callback(struct netif *netif, acd_callback_enum_t state)
|
||||
autoip_restart(netif);
|
||||
break;
|
||||
case ACD_DECLINE:
|
||||
/* "delete" conflicting address so a new one will be selected in
|
||||
* autoip_start() */
|
||||
/* "delete" conflicting address and increment tried addr so a new one
|
||||
* will be selected in autoip_start() */
|
||||
ip4_addr_set_any(&autoip->llipaddr);
|
||||
autoip->tried_llipaddr++;
|
||||
autoip_stop(netif);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -773,9 +773,6 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
|
||||
* @ingroup dhcp4
|
||||
* Removes a struct dhcp from a netif.
|
||||
*
|
||||
* ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
|
||||
* struct dhcp since the memory is passed back to the heap.
|
||||
*
|
||||
* @param netif the netif from which to remove the struct dhcp
|
||||
*/
|
||||
void dhcp_cleanup(struct netif *netif)
|
||||
@@ -811,6 +808,7 @@ dhcp_start(struct netif *netif)
|
||||
{
|
||||
struct dhcp *dhcp;
|
||||
err_t result;
|
||||
u8_t saved_flags;
|
||||
|
||||
LWIP_ASSERT_CORE_LOCKED();
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
|
||||
@@ -833,6 +831,8 @@ dhcp_start(struct netif *netif)
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* clear the flags, the rest is cleared below */
|
||||
dhcp->flags = 0;
|
||||
/* store this dhcp client in the netif */
|
||||
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp\n"));
|
||||
@@ -846,9 +846,10 @@ dhcp_start(struct netif *netif)
|
||||
/* dhcp is cleared below, no need to reset flag*/
|
||||
}
|
||||
|
||||
/* clear data structure */
|
||||
/* clear data structure but preserve DHCP_FLAG_EXTERNAL_MEM for dhcp_cleanup() */
|
||||
saved_flags = dhcp->flags;
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
|
||||
dhcp->flags = saved_flags & DHCP_FLAG_EXTERNAL_MEM;
|
||||
|
||||
|
||||
#if LWIP_DHCP_DOES_ACD_CHECK
|
||||
|
||||
@@ -940,9 +940,9 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
|
||||
netif_addr_idx_t i;
|
||||
|
||||
/* non-unicast address? */
|
||||
if (ip4_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip4_addr_ismulticast(ipaddr) ||
|
||||
ip4_addr_isany(ipaddr)) {
|
||||
if (ip4_addr_isany(ipaddr) ||
|
||||
ip4_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip4_addr_ismulticast(ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
@@ -175,19 +175,21 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
|
||||
|
||||
MIB2_STATS_INC(mib2.ipreasmfails);
|
||||
#if LWIP_ICMP
|
||||
iprh = (struct ip_reass_helper *)ipr->p->payload;
|
||||
if (iprh->start == 0) {
|
||||
/* The first fragment was received, send ICMP time exceeded. */
|
||||
/* First, de-queue the first pbuf from r->p. */
|
||||
p = ipr->p;
|
||||
ipr->p = iprh->next_pbuf;
|
||||
/* Then, copy the original header into it. */
|
||||
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
|
||||
icmp_time_exceeded(p, ICMP_TE_FRAG);
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||
pbuf_free(p);
|
||||
if (ipr->p != NULL) {
|
||||
iprh = (struct ip_reass_helper *)ipr->p->payload;
|
||||
if (iprh->start == 0) {
|
||||
/* The first fragment was received, send ICMP time exceeded. */
|
||||
/* First, de-queue the first pbuf from r->p. */
|
||||
p = ipr->p;
|
||||
ipr->p = iprh->next_pbuf;
|
||||
/* Then, copy the original header into it. */
|
||||
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
|
||||
icmp_time_exceeded(p, ICMP_TE_FRAG);
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_ICMP */
|
||||
|
||||
|
||||
@@ -154,35 +154,37 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
||||
struct ip6_reass_helper *iprh;
|
||||
|
||||
#if LWIP_ICMP6
|
||||
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
||||
if (iprh->start == 0) {
|
||||
/* The first fragment was received, send ICMP time exceeded. */
|
||||
/* First, de-queue the first pbuf from r->p. */
|
||||
p = ipr->p;
|
||||
ipr->p = iprh->next_pbuf;
|
||||
/* Restore the part that we've overwritten with our helper structure, or we
|
||||
* might send garbage (and disclose a pointer) in the ICMPv6 reply. */
|
||||
MEMCPY(p->payload, ipr->orig_hdr, sizeof(*iprh));
|
||||
/* Then, move back to the original ipv6 header (we are now pointing to Fragment header).
|
||||
This cannot fail since we already checked when receiving this fragment. */
|
||||
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)ipr->iphdr))) {
|
||||
LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed", 0);
|
||||
if (ipr->p != NULL) {
|
||||
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
||||
if (iprh->start == 0) {
|
||||
/* The first fragment was received, send ICMP time exceeded. */
|
||||
/* First, de-queue the first pbuf from r->p. */
|
||||
p = ipr->p;
|
||||
ipr->p = iprh->next_pbuf;
|
||||
/* Restore the part that we've overwritten with our helper structure, or we
|
||||
* might send garbage (and disclose a pointer) in the ICMPv6 reply. */
|
||||
MEMCPY(p->payload, ipr->orig_hdr, sizeof(*iprh));
|
||||
/* Then, move back to the original ipv6 header (we are now pointing to Fragment header).
|
||||
This cannot fail since we already checked when receiving this fragment. */
|
||||
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)ipr->iphdr))) {
|
||||
LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed", 0);
|
||||
}
|
||||
else {
|
||||
/* Reconstruct the zoned source and destination addresses, so that we do
|
||||
* not end up sending the ICMP response over the wrong link. */
|
||||
ip6_addr_t src_addr, dest_addr;
|
||||
ip6_addr_copy_from_packed(src_addr, IPV6_FRAG_SRC(ipr));
|
||||
ip6_addr_set_zone(&src_addr, ipr->src_zone);
|
||||
ip6_addr_copy_from_packed(dest_addr, IPV6_FRAG_DEST(ipr));
|
||||
ip6_addr_set_zone(&dest_addr, ipr->dest_zone);
|
||||
/* Send the actual ICMP response. */
|
||||
icmp6_time_exceeded_with_addrs(p, ICMP6_TE_FRAG, &src_addr, &dest_addr);
|
||||
}
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||
pbuf_free(p);
|
||||
}
|
||||
else {
|
||||
/* Reconstruct the zoned source and destination addresses, so that we do
|
||||
* not end up sending the ICMP response over the wrong link. */
|
||||
ip6_addr_t src_addr, dest_addr;
|
||||
ip6_addr_copy_from_packed(src_addr, IPV6_FRAG_SRC(ipr));
|
||||
ip6_addr_set_zone(&src_addr, ipr->src_zone);
|
||||
ip6_addr_copy_from_packed(dest_addr, IPV6_FRAG_DEST(ipr));
|
||||
ip6_addr_set_zone(&dest_addr, ipr->dest_zone);
|
||||
/* Send the actual ICMP response. */
|
||||
icmp6_time_exceeded_with_addrs(p, ICMP6_TE_FRAG, &src_addr, &dest_addr);
|
||||
}
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif /* LWIP_ICMP6 */
|
||||
|
||||
|
||||
@@ -1993,17 +1993,17 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
||||
return;
|
||||
}
|
||||
/* TCP timestamp option with valid length */
|
||||
tsval = tcp_get_next_optbyte();
|
||||
tsval |= (tcp_get_next_optbyte() << 8);
|
||||
tsval = (tcp_get_next_optbyte() << 24);
|
||||
tsval |= (tcp_get_next_optbyte() << 16);
|
||||
tsval |= (tcp_get_next_optbyte() << 24);
|
||||
tsval |= (tcp_get_next_optbyte() << 8);
|
||||
tsval |= tcp_get_next_optbyte();
|
||||
if (flags & TCP_SYN) {
|
||||
pcb->ts_recent = lwip_ntohl(tsval);
|
||||
pcb->ts_recent = tsval;
|
||||
/* Enable sending timestamps in every segment now that we know
|
||||
the remote host supports it. */
|
||||
tcp_set_flags(pcb, TF_TIMESTAMP);
|
||||
} else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno + tcplen)) {
|
||||
pcb->ts_recent = lwip_ntohl(tsval);
|
||||
pcb->ts_recent = tsval;
|
||||
}
|
||||
/* Advance to next option (6 bytes already read) */
|
||||
tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
#ifndef MDNS_TXT_RDATA_SIZE
|
||||
# define MDNS_TXT_RDATA_SIZE 256
|
||||
#endif
|
||||
|
||||
/** MDNS_RESP_USENETIF_EXTCALLBACK==1: register an ext_callback on the netif
|
||||
* to automatically restart probing/announcing on status or address change.
|
||||
*/
|
||||
|
||||
@@ -90,10 +90,16 @@ struct mdns_request {
|
||||
};
|
||||
#endif
|
||||
|
||||
/** TXT record data */
|
||||
struct mdns_txtdata {
|
||||
u8_t rdata[MDNS_TXT_RDATA_SIZE];
|
||||
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' */
|
||||
|
||||
@@ -54,11 +54,11 @@ extern "C" {
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 2
|
||||
/** x.x.X: Revision of the stack */
|
||||
#define LWIP_VERSION_REVISION 1
|
||||
#define LWIP_VERSION_REVISION 2
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
#define LWIP_VERSION_RC LWIP_RC_RELEASE
|
||||
#define LWIP_VERSION_RC LWIP_RC_DEVELOPMENT
|
||||
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||
#define LWIP_RC_RELEASE 255
|
||||
|
||||
@@ -519,6 +519,7 @@ START_TEST(test_ip6_reass)
|
||||
test_ip6_reass_helper(130, t3, NUM_SEGS, 8);
|
||||
test_ip6_reass_helper(130, t4, NUM_SEGS, 1448);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/apps/mdns.h"
|
||||
#include "lwip/apps/mdns_domain.h"
|
||||
#include "lwip/apps/mdns_out.h"
|
||||
#include "lwip/apps/mdns_priv.h"
|
||||
|
||||
START_TEST(readname_basic)
|
||||
@@ -876,6 +877,155 @@ START_TEST(compress_long_match)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define TXT_STRING_1 "path=/"
|
||||
#define TXT_LENGTH_1 6
|
||||
#define TXT_LENSTR_1 "\006"
|
||||
|
||||
#define TXT_STRING_2 ""
|
||||
#define TXT_LENGTH_2 0
|
||||
#define TXT_LENSTR_2 "\000"
|
||||
|
||||
#define TXT_STRING_3 "This sentence is sixty-three bytes long, including punctuation."
|
||||
#define TXT_LENGTH_3 63
|
||||
#define TXT_LENSTR_3 "\077"
|
||||
|
||||
#define TXT_STRING_4 "This tests whether mdns_resp_add_service_txtitem can properly handle strings longer than 63 characters."
|
||||
#define TXT_LENGTH_4 103
|
||||
#define TXT_LENSTR_4 "\147"
|
||||
|
||||
START_TEST(txt_short_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_1 TXT_STRING_1;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_1;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_1, TXT_LENGTH_1);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_empty_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_2 TXT_STRING_2;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_2;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_2, TXT_LENGTH_2);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_long_item)
|
||||
{
|
||||
const char *expected_txtdata = TXT_LENSTR_4 TXT_STRING_4;
|
||||
const size_t expected_txtdata_length = 1 + TXT_LENGTH_4;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_4, TXT_LENGTH_4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_multiple_items)
|
||||
{
|
||||
const char *expected_txtdata = (
|
||||
TXT_LENSTR_1
|
||||
TXT_STRING_1
|
||||
TXT_LENSTR_2
|
||||
TXT_STRING_2
|
||||
TXT_LENSTR_3
|
||||
TXT_STRING_3
|
||||
TXT_LENSTR_4
|
||||
TXT_STRING_4
|
||||
);
|
||||
const size_t expected_txtdata_length = (
|
||||
1 + TXT_LENGTH_1
|
||||
+ 1 + TXT_LENGTH_2
|
||||
+ 1 + TXT_LENGTH_3
|
||||
+ 1 + TXT_LENGTH_4
|
||||
);
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_1, TXT_LENGTH_1);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_1 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_2, TXT_LENGTH_2);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_1 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_3, TXT_LENGTH_3);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_3 */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_4, TXT_LENGTH_4);
|
||||
fail_unless(res == ERR_OK); /* TXT_STRING_4 */
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(txt_buffer_full)
|
||||
{
|
||||
const char *expected_txtdata = (
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
TXT_LENSTR_3 TXT_STRING_3
|
||||
);
|
||||
const size_t expected_txtdata_length = 256;
|
||||
|
||||
struct mdns_service service;
|
||||
err_t res;
|
||||
int i;
|
||||
memset(&service, 0, sizeof(struct mdns_service));
|
||||
|
||||
mdns_prepare_txtdata(&service);
|
||||
|
||||
/* add a 64-byte string 4 times = 256 bytes */
|
||||
for (i = 0; i < 4; i++) {
|
||||
res = mdns_resp_add_service_txtitem(&service, TXT_STRING_3, TXT_LENGTH_3);
|
||||
ck_assert_msg(res == ERR_OK,
|
||||
"adding text item failed with error %d (i=%d, txtdata.length=%d)",
|
||||
res, i, service.txtdata.length);
|
||||
}
|
||||
|
||||
/* Try to add a few more strings while the buffer is full. This should fail. */
|
||||
res = mdns_resp_add_service_txtitem(&service, "", 0);
|
||||
fail_unless(res != ERR_OK); /* empty string */
|
||||
|
||||
res = mdns_resp_add_service_txtitem(&service, "path=/", 6);
|
||||
fail_unless(res != ERR_OK); /* short string */
|
||||
|
||||
fail_unless(service.txtdata.length == expected_txtdata_length);
|
||||
fail_if(memcmp(service.txtdata.rdata, expected_txtdata, expected_txtdata_length));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite* mdns_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
@@ -911,6 +1061,12 @@ Suite* mdns_suite(void)
|
||||
TESTFUNC(compress_2nd_label_short),
|
||||
TESTFUNC(compress_jump_to_jump),
|
||||
TESTFUNC(compress_long_match),
|
||||
|
||||
TESTFUNC(txt_short_item),
|
||||
TESTFUNC(txt_empty_item),
|
||||
TESTFUNC(txt_long_item),
|
||||
TESTFUNC(txt_multiple_items),
|
||||
TESTFUNC(txt_buffer_full),
|
||||
};
|
||||
return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -534,15 +534,13 @@ START_TEST(test_tcp_fast_retx_recover)
|
||||
EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||
EXPECT_RET(txcounters.num_tx_bytes == 0);
|
||||
memset(&txcounters, 0, sizeof(txcounters));
|
||||
|
||||
do
|
||||
{
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
|
||||
i++;
|
||||
}while(err == ERR_OK);
|
||||
EXPECT_RET(err != ERR_OK);
|
||||
}
|
||||
err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
|
||||
}while(err == ERR_OK);
|
||||
EXPECT_RET(err != ERR_OK);
|
||||
|
||||
err = tcp_output(pcb);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
/*EXPECT_RET(txcounters.num_tx_calls == 0);
|
||||
|
||||
Reference in New Issue
Block a user