Commit 3479010e authored by Jukka Rissanen's avatar Jukka Rissanen Committed by Ioannis Glaropoulos
Browse files

net: dns: Check and parse received mDNS responses properly



The mDNS packet receive had issues:

* The DNS id needs to be 0 for both sending and receiving, we did
  not accepted 0 incoming id.
* The mDNS response does not have any questions in it so we just
  need to skip the question count checks in response.
* Skip the Cache-Flush bit in Class field so that we can properly
  parse CLASS_IN value.

Signed-off-by: default avatarJukka Rissanen <jukka.rissanen@linux.intel.com>
parent 9fdd41be
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -113,7 +113,9 @@ int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, u32_t *ttl)
	u8_t *answer;

	answer = dns_msg->msg + dns_msg->answer_offset;
	dname_len = skip_fqdn(answer, dns_msg->msg_size - dns_msg->answer_offset);

	dname_len = skip_fqdn(answer,
			      dns_msg->msg_size - dns_msg->answer_offset);
	if (dname_len < 0) {
		return dname_len;
	}
@@ -134,9 +136,12 @@ int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, u32_t *ttl)
		return -EINVAL;
	}

	/* Only DNS_CLASS_IN answers
	/* Only DNS_CLASS_IN answers. If mDNS is enabled, strip away the
	 * Cache-Flush bit (highest one).
	 */
	if (dns_answer_class(dname_len, answer) != DNS_CLASS_IN) {
	if ((dns_answer_class(dname_len, answer) &
	     (IS_ENABLED(CONFIG_MDNS_RESOLVER) ? 0x7fff : 0xffff))
							!= DNS_CLASS_IN) {
		return -EINVAL;
	}

@@ -210,7 +215,11 @@ int dns_unpack_response_header(struct dns_msg_t *msg, int src_id)

	qdcount = dns_unpack_header_qdcount(dns_header);
	ancount = dns_unpack_header_ancount(dns_header);
	if (qdcount < 1 || ancount < 1) {

	/* For mDNS (when src_id == 0) the query count is 0 so accept
	 * the packet in that case.
	 */
	if ((qdcount < 1 && src_id > 0) || ancount < 1) {
		return -EINVAL;
	}

+28 −16
Original line number Diff line number Diff line
@@ -413,16 +413,27 @@ static int dns_read(struct dns_resolve_context *ctx,
	}

	if (dns_header_qdcount(dns_msg.msg) != 1) {
		/* For mDNS (when dns_id == 0) the query count is 0 */
		if (*dns_id > 0) {
			ret = DNS_EAI_FAIL;
			goto quit;
		}
	}

	ret = dns_unpack_response_query(&dns_msg);
	if (ret < 0) {
		/* Check mDNS like above */
		if (*dns_id > 0) {
			ret = DNS_EAI_FAIL;
			goto quit;
		}

		/* mDNS responses to do not have the query part so the
		 * answer starts immediately after the header.
		 */
		dns_msg.answer_offset = dns_msg.query_offset;
	}

	if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_A) {
		address_size = DNS_IPV4_LEN;
		addr = (u8_t *)&net_sin(&info.ai_addr)->sin_addr;
@@ -839,19 +850,9 @@ try_resolve:

	ctx->queries[i].id = sys_rand32_get();

	/* Do this immediately after calculating the Id so that the unit
	 * test will work properly.
	 */
	if (dns_id) {
		*dns_id = ctx->queries[i].id;

		NET_DBG("DNS id will be %u", *dns_id);
	}

	mdns_query = false;

	/* If mDNS is enabled, then send .local queries only to multicast
	 * address.
	 * address. For mDNS the id should be set to 0, see RFC 6762 ch. 18.1
	 * for details.
	 */
	if (IS_ENABLED(CONFIG_MDNS_RESOLVER)) {
		const char *ptr = strrchr(query, '.');
@@ -859,9 +860,20 @@ try_resolve:
		/* Note that we memcmp() the \0 here too */
		if (ptr && !memcmp(ptr, (const void *){ ".local" }, 7)) {
			mdns_query = true;

			ctx->queries[i].id = 0;
		}
	}

	/* Do this immediately after calculating the Id so that the unit
	 * test will work properly.
	 */
	if (dns_id) {
		*dns_id = ctx->queries[i].id;

		NET_DBG("DNS id will be %u", *dns_id);
	}

	for (j = 0; j < SERVER_COUNT; j++) {
		hop_limit = 0U;