switch (p->protocol) {
- case DNS_PROTOCOL_LLMNR:
case DNS_PROTOCOL_DNS:
- if (DNS_PACKET_TC(p)) /* mDNS query may have truncation flag. */
+ if (DNS_PACKET_TC(p))
+ return -EBADMSG;
+
+ if (DNS_PACKET_QDCOUNT(p) != 1)
+ return -EBADMSG;
+
+ if (DNS_PACKET_ANCOUNT(p) > 0)
+ return -EBADMSG;
+
+ /* Note, in most cases, DNS query packet does not have authority section. But some query
+ * types, e.g. IXFR, have Authority sections. Hence, unlike the check for LLMNR, we do not
+ * check DNS_PACKET_NSCOUNT(p) here. */
+ break;
+
+ case DNS_PROTOCOL_LLMNR:
+ if (DNS_PACKET_TC(p))
return -EBADMSG;
/* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
break;
case DNS_PROTOCOL_MDNS:
+ /* Note, mDNS query may have truncation flag. So, unlike the check for DNS and LLMNR,
+ * we do not check DNS_PACKET_TC(p) here. */
+
/* RFC 6762, Section 18 specifies that messages with non-zero RCODE
* must be silently ignored, and that we must ignore the values of
* AA, RD, RA, AD, and CD bits. */
return dns_packet_compare_func(a, b) == 0;
}
-int dns_packet_ede_rcode(DnsPacket *p, char **ret_ede_msg) {
- assert(p);
-
- _cleanup_free_ char *msg = NULL, *msg_escaped = NULL;
- int ede_rcode = _DNS_EDNS_OPT_MAX_DEFINED;
- int r;
+int dns_packet_ede_rcode(DnsPacket *p, int *ret_ede_rcode, char **ret_ede_msg) {
const uint8_t *d;
size_t l;
+ int r;
+
+ assert(p);
if (!p->opt)
- return _DNS_EDE_RCODE_INVALID;
+ return -ENOENT;
d = p->opt->opt.data;
l = p->opt->opt.data_size;
"Truncated option in EDNS0 variable part.");
if (code == DNS_EDNS_OPT_EXT_ERROR) {
+ _cleanup_free_ char *msg = NULL;
+
if (length < 2U)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
- "EDNS0 truncated EDE info code.");
- ede_rcode = unaligned_read_be16(d + 4);
- r = make_cstring((char *)d + 6, length - 2U, MAKE_CSTRING_ALLOW_TRAILING_NUL, &msg);
+ "EDNS0 truncated EDE info code.");
+
+ r = make_cstring((char *) d + 6, length - 2U, MAKE_CSTRING_ALLOW_TRAILING_NUL, &msg);
if (r < 0)
- return log_debug_errno(r, "Invalid EDE text in opt");
- else if (!utf8_is_valid(msg))
- return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Invalid EDE text in opt");
- else if (ede_rcode < _DNS_EDNS_OPT_MAX_DEFINED) {
- msg_escaped = cescape(msg);
- if (!msg_escaped)
- return -ENOMEM;
+ return log_debug_errno(r, "Invalid EDE text in opt.");
+
+ if (ret_ede_msg) {
+ if (!utf8_is_valid(msg)) {
+ _cleanup_free_ char *msg_escaped = NULL;
+
+ msg_escaped = cescape(msg);
+ if (!msg_escaped)
+ return log_oom_debug();
+
+ *ret_ede_msg = TAKE_PTR(msg_escaped);
+ } else
+ *ret_ede_msg = TAKE_PTR(msg);
}
- break;
+
+ if (ret_ede_rcode)
+ *ret_ede_rcode = unaligned_read_be16(d + 4);
+
+ return 0;
}
d += 4U + length;
l -= 4U + length;
}
- if (ret_ede_msg)
- *ret_ede_msg = TAKE_PTR(msg_escaped);
-
- return ede_rcode;
+ return -ENOENT;
}
bool dns_ede_rcode_is_dnssec(int ede_rcode) {
[DNS_RCODE_NXRRSET] = "NXRRSET",
[DNS_RCODE_NOTAUTH] = "NOTAUTH",
[DNS_RCODE_NOTZONE] = "NOTZONE",
+ [DNS_RCODE_DSOTYPENI] = "DSOTYPENI",
[DNS_RCODE_BADVERS] = "BADVERS",
[DNS_RCODE_BADKEY] = "BADKEY",
[DNS_RCODE_BADTIME] = "BADTIME",