h = DNS_PACKET_HEADER(p);
- if (protocol == DNS_PROTOCOL_DNS)
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0)); /* ask for recursion */
+ if (protocol == DNS_PROTOCOL_LLMNR)
+ h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
+ 0 /* opcode */,
+ 0 /* c */,
+ 0 /* tc */,
+ 0 /* t */,
+ 0 /* ra */,
+ 0 /* ad */,
+ 0 /* cd */,
+ 0 /* rcode */));
else
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0));
+ h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
+ 0 /* opcode */,
+ 0 /* aa */,
+ 0 /* tc */,
+ 1 /* rd (ask for recursion) */,
+ 0 /* ra */,
+ 0 /* ad */,
+ 0 /* cd */,
+ 0 /* rcode */));
*ret = p;
return 0;
if (DNS_PACKET_OPCODE(p) != 0)
return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
+ if (p->protocol == DNS_PROTOCOL_LLMNR &&
+ DNS_PACKET_QDCOUNT(p) != 1)
+ return -EBADMSG;
+
return 1;
}
if (DNS_PACKET_TC(p))
return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
if (p->protocol == DNS_PROTOCOL_LLMNR &&
DNS_PACKET_QDCOUNT(p) != 1)
return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
if (DNS_PACKET_ANCOUNT(p) > 0)
return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
if (DNS_PACKET_NSCOUNT(p) > 0)
return -EBADMSG;
#define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15)
#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
#define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1)
+#define DNS_PACKET_C(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
+#define DNS_PACKET_T(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
#define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount)
#define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount)
#define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount)
if (p->family != t->scope->family)
return;
+ /* Don't accept UDP packets directed to anything but
+ * the LLMNR multicast addresses. */
+
if (p->ipproto == IPPROTO_UDP) {
if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
return;
if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
return;
}
+
+ /* Tentative replies shall be discarded, see RFC 4795,
+ * 2.1.1 */
+
+ if (DNS_PACKET_T(p))
+ return;
}
if (t->scope->protocol == DNS_PROTOCOL_DNS) {
return r;
DNS_PACKET_HEADER(p)->id = id;
- DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(1, 0, 0, 0, 0, 0, 0, 0, rcode));
+ DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
+ 1 /* qr */,
+ 0 /* opcode */,
+ 0 /* c */,
+ 0 /* tc */,
+ 0 /* t */,
+ 0 /* (ra) */,
+ 0 /* (ad) */,
+ 0 /* (cd) */,
+ rcode));
if (q) {
for (i = 0; i < q->n_keys; i++) {
return;
}
+ if (DNS_PACKET_C(p)) {
+ /* FIXME: Somebody notified us about a likely conflict */
+ return;
+ }
+
r = dns_zone_lookup(&s->zone, p->question, &answer);
if (r < 0) {
log_debug("Failed to lookup key: %s", strerror(-r));