unsigned char *p, *ansp;
int qtype, qclass, rc;
int nameoffset, axfroffset = 0;
- int q, anscount = 0, authcount = 0;
+ int anscount = 0, authcount = 0;
struct crec *crecp;
- int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0;
+ int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0, notimp = 0;
struct auth_zone *zone = NULL;
struct addrlist *subnet = NULL;
char *cut;
unsigned int wclen;
unsigned int log_flags = local_query ? 0 : F_NOERR;
- if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
+ if (ntohs(header->qdcount) != 1)
return 0;
/* determine end of question section (we put answers there) */
if (!(ansp = skip_questions(header, qlen)))
return 0; /* bad packet */
- /* now process each question, answers go in RRs after the question */
p = (unsigned char *)(header+1);
- for (q = ntohs(header->qdcount); q != 0; q--)
+ if (OPCODE(header) != QUERY)
+ notimp = 1;
+ else
{
unsigned int flag = 0;
int found = 0;
{
auth = 0;
out_of_zone = 1;
- continue;
+ goto done;
}
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
{
out_of_zone = 1;
auth = 0;
- continue;
+ goto done;
}
else if (qtype == T_SOA)
soa = 1, found = 1;
else
log_query(log_flags | flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL, 0);
- continue;
+ goto done;
}
cname_restart:
{
out_of_zone = 1;
auth = 0;
- continue;
+ goto done;
}
}
}
}
+
+ done:
/* Add auth section */
if (auth && zone)
header->nscount = htons(authcount);
header->arcount = htons(0);
- if (!local_query && out_of_zone)
+ if ((!local_query && out_of_zone) || notimp)
{
- SET_RCODE(header, REFUSED);
+ if (out_of_zone)
+ {
+ addr.log.rcode = REFUSED;
+ addr.log.ede = EDE_NOT_AUTH;
+ }
+ else
+ {
+ addr.log.rcode = NOTIMP;
+ addr.log.ede = EDE_UNSET;
+ }
+
+ SET_RCODE(header, addr.log.rcode);
header->ancount = htons(0);
header->nscount = htons(0);
- addr.log.rcode = REFUSED;
- addr.log.ede = EDE_NOT_AUTH;
log_query(log_flags | F_UPSTREAM | F_RCODE, "error", &addr, NULL, 0);
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
}
char *extra = "";
char *gap = " ";
char portstring[7]; /* space for #<portnum> */
-
+ char opcodestring[3]; /* maximum is 15 */
+
if (!option_bool(OPT_LOG))
return;
return;
/* build query type string if requested */
- if (!(flags & (F_SERVER | F_IPSET)) && type > 0)
+ if (!(flags & (F_SERVER | F_IPSET | F_QUERY)) && type > 0)
arg = querystr(arg, type);
dest = arg;
source = arg;
else if (flags & F_UPSTREAM)
source = "reply";
+ else if (flags & F_AUTH)
+ source = "auth";
else if (flags & F_SECSTAT)
{
if (addr && addr->log.ede != EDE_UNSET && option_bool(OPT_EXTRALOG))
source = "validation";
dest = arg;
}
- else if (flags & F_AUTH)
- source = "auth";
else if (flags & F_DNSSEC)
{
source = arg;
source = "forwarded";
verb = "to";
}
- else if (flags & F_QUERY)
- {
- source = arg;
- verb = "from";
- }
else if (flags & F_IPSET)
{
source = type ? "ipset add" : "nftset add";
source = "cached-stale";
else
source = "cached";
-
+
+ if (flags & F_QUERY)
+ {
+ if (flags & F_CONFIG)
+ {
+ sprintf(opcodestring, "%u", type & 0xf);
+ source = "non-query opcode";
+ name = opcodestring;
+ }
+ else if (!(flags & F_AUTH))
+ source = "query";
+
+ verb = "from";
+ }
+
if (!name)
gap = name = "";
else if (!name[0])
#endif
if (OPCODE(header) != QUERY)
- log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &source_addr, "non-query", 0);
+ log_query_mysockaddr((auth_dns ? F_NOERR : 0) | F_QUERY | F_FORWARD | F_CONFIG, NULL, &source_addr, NULL, OPCODE(header));
else if (extract_request(header, (size_t)n, daemon->namebuff, &type, NULL))
{
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
- log_query_mysockaddr((auth_dns ? F_NOERR : 0 ) | F_QUERY | F_FORWARD, daemon->namebuff,
- &source_addr, auth_dns ? "auth" : "query", type);
+ log_query_mysockaddr((auth_dns ? F_NOERR | F_AUTH : 0 ) | F_QUERY | F_FORWARD, daemon->namebuff,
+ &source_addr, NULL, type);
#ifdef HAVE_AUTH
/* Find queries for zones we're authoritative for, and answer them directly.
if (OPCODE(header) != QUERY)
{
- log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &peer_addr, "non-query", 0);
+ log_query_mysockaddr((auth_dns ? F_NOERR : 0) | F_QUERY | F_FORWARD | F_CONFIG, NULL, &peer_addr, NULL, OPCODE(header));
gotname = 0;
flags = F_RCODE;
}
saved_question = blockdata_alloc((char *)header, (size_t)size);
saved_size = size;
- log_query_mysockaddr((auth_dns ? F_NOERR : 0) | F_QUERY | F_FORWARD, daemon->namebuff,
- &peer_addr, auth_dns ? "auth" : "query", qtype);
+ log_query_mysockaddr((auth_dns ? F_NOERR | F_AUTH : 0) | F_QUERY | F_FORWARD, daemon->namebuff,
+ &peer_addr, NULL, qtype);
#ifdef HAVE_AUTH
/* Find queries for zones we're authoritative for, and answer them directly.