OpenDNSSEC-signer  1.4.1
query.c
Go to the documentation of this file.
1 /*
2  * $Id: query.c 4958 2011-04-18 07:11:09Z matthijs $
3  *
4  * Copyright (c) 2011 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "daemon/dnshandler.h"
36 #include "daemon/engine.h"
37 #include "shared/util.h"
38 #include "wire/axfr.h"
39 #include "wire/query.h"
40 
41 const char* query_str = "query";
42 
43 
50 {
51  allocator_type* allocator = NULL;
52  query_type* q = NULL;
53  allocator = allocator_create(malloc, free);
54  if (!allocator) {
55  return NULL;
56  }
57  q = (query_type*) allocator_alloc(allocator, sizeof(query_type));
58  if (!q) {
59  allocator_cleanup(allocator);
60  return NULL;
61  }
62  q->allocator = allocator;
63  q->buffer = NULL;
64  q->tsig_rr = NULL;
65  q->buffer = buffer_create(allocator, PACKET_BUFFER_SIZE);
66  if (!q->buffer) {
67  query_cleanup(q);
68  return NULL;
69  }
70  q->tsig_rr = tsig_rr_create(allocator);
71  if (!q->tsig_rr) {
72  query_cleanup(q);
73  return NULL;
74  }
75  q->edns_rr = edns_rr_create(allocator);
76  if (!q->edns_rr) {
77  query_cleanup(q);
78  return NULL;
79  }
81  return q;
82 }
83 
84 
89 void
90 query_reset(query_type* q, size_t maxlen, int is_tcp)
91 {
92  if (!q) {
93  return;
94  }
95  q->addrlen = sizeof(q->addr);
96  q->maxlen = maxlen;
97  q->reserved_space = 0;
98  buffer_clear(q->buffer);
99  tsig_rr_reset(q->tsig_rr, NULL, NULL);
101  q->tsig_prepare_it = 1;
102  q->tsig_update_it = 1;
103  q->tsig_sign_it = 1;
104  q->tcp = is_tcp;
105  /* qname, qtype, qclass */
106  q->zone = NULL;
107  /* domain, opcode, cname count, delegation, compression, temp */
108  q->axfr_is_done = 0;
109  q->axfr_fd = NULL;
110  q->serial = 0;
111  q->startpos = 0;
112  return;
113 }
114 
115 
120 static query_state
121 query_error(query_type* q, ldns_pkt_rcode rcode)
122 {
123  size_t limit = 0;
124  if (!q) {
125  return QUERY_DISCARDED;
126  }
127  limit = buffer_limit(q->buffer);
128  buffer_clear(q->buffer);
130  buffer_pkt_set_rcode(q->buffer, rcode);
134  buffer_set_position(q->buffer, limit);
135  return QUERY_PROCESSED;
136 }
137 
138 
143 static query_state
144 query_formerr(query_type* q)
145 {
146  ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
147  if (!q) {
148  return QUERY_DISCARDED;
149  }
150  opcode = buffer_pkt_opcode(q->buffer);
151  /* preserve the RD flag, clear the rest */
153  buffer_pkt_set_opcode(q->buffer, opcode);
155  ods_log_debug("[%s] formerr", query_str);
156  return query_error(q, LDNS_RCODE_FORMERR);
157 }
158 
159 
164 static query_state
165 query_servfail(query_type* q)
166 {
167  if (!q) {
168  return QUERY_DISCARDED;
169  }
170  ods_log_debug("[%s] servfail", query_str);
174  return query_error(q, LDNS_RCODE_SERVFAIL);
175 }
176 
177 
182 static query_state
183 query_notimpl(query_type* q)
184 {
185  if (!q) {
186  return QUERY_DISCARDED;
187  }
188  ods_log_debug("[%s] notimpl", query_str);
189  return query_error(q, LDNS_RCODE_NOTIMPL);
190 }
191 
192 
197 static query_state
198 query_refused(query_type* q)
199 {
200  if (!q) {
201  return QUERY_DISCARDED;
202  }
203  ods_log_debug("[%s] refused", query_str);
204  return query_error(q, LDNS_RCODE_REFUSED);
205 }
206 
207 
212 static query_state
213 query_notauth(query_type* q)
214 {
215  if (!q) {
216  return QUERY_DISCARDED;
217  }
218  ods_log_debug("[%s] notauth", query_str);
219  return query_error(q, LDNS_RCODE_NOTAUTH);
220 }
221 
222 
228 static int
229 query_parse_soa(buffer_type* buffer, uint32_t* serial)
230 {
231  ldns_rr_type type = 0;
232  ods_log_assert(buffer);
233  if (!buffer_available(buffer, 10)) {
234  ods_log_error("[%s] bad soa: packet too short", query_str);
235  return 0;
236  }
237  type = (ldns_rr_type) buffer_read_u16(buffer);
238  if (type != LDNS_RR_TYPE_SOA) {
239  ods_log_error("[%s] bad soa: rr is not soa (%d)", query_str, type);
240  return 0;
241  }
242  (void)buffer_read_u16(buffer);
243  (void)buffer_read_u32(buffer);
244  /* rdata length */
245  if (!buffer_available(buffer, buffer_read_u16(buffer))) {
246  ods_log_error("[%s] bad soa: missing rdlength", query_str);
247  return 0;
248  }
249  /* MNAME */
250  if (!buffer_skip_dname(buffer)) {
251  ods_log_error("[%s] bad soa: missing mname", query_str);
252  return 0;
253  }
254  /* RNAME */
255  if (!buffer_skip_dname(buffer)) {
256  ods_log_error("[%s] bad soa: missing rname", query_str);
257  return 0;
258  }
259  if (serial) {
260  *serial = buffer_read_u32(buffer);
261  }
262  return 1;
263 }
264 
265 
270 static query_state
271 query_process_notify(query_type* q, ldns_rr_type qtype, void* engine)
272 {
273  engine_type* e = (engine_type*) engine;
274  dnsin_type* dnsin = NULL;
275  uint16_t count = 0;
276  uint16_t rrcount = 0;
277  uint32_t serial = 0;
278  size_t pos = 0;
279  char address[128];
280  if (!e || !q || !q->zone) {
281  return QUERY_DISCARDED;
282  }
284  ods_log_assert(q->zone->name);
285  ods_log_debug("[%s] incoming notify for zone %s", query_str,
286  q->zone->name);
287  if (buffer_pkt_rcode(q->buffer) != LDNS_RCODE_NOERROR ||
288  buffer_pkt_qr(q->buffer) ||
289  !buffer_pkt_aa(q->buffer) ||
290  buffer_pkt_tc(q->buffer) ||
291  buffer_pkt_rd(q->buffer) ||
292  buffer_pkt_ra(q->buffer) ||
293  buffer_pkt_ad(q->buffer) ||
294  buffer_pkt_cd(q->buffer) ||
295  buffer_pkt_qdcount(q->buffer) != 1 ||
296  buffer_pkt_ancount(q->buffer) > 1 ||
297  qtype != LDNS_RR_TYPE_SOA) {
298  return query_formerr(q);
299  }
300  if (!q->zone->adinbound || q->zone->adinbound->type != ADAPTER_DNS) {
301  ods_log_error("[%s] zone %s is not configured to have input dns "
302  "adapter", query_str, q->zone->name);
303  return query_notauth(q);
304  }
306  dnsin = (dnsin_type*) q->zone->adinbound->config;
307  if (!acl_find(dnsin->allow_notify, &q->addr, q->tsig_rr)) {
308  if (addr2ip(q->addr, address, sizeof(address))) {
309  ods_log_info("[%s] unauthorized notify for zone %s from client %s: "
310  "no acl matches", query_str, q->zone->name, address);
311  } else {
312  ods_log_info("[%s] unauthorized notify for zone %s from unknown "
313  "client: no acl matches", query_str, q->zone->name);
314  }
315  return query_notauth(q);
316  }
317  ods_log_assert(q->zone->xfrd);
318  /* skip header and question section */
320  count = buffer_pkt_qdcount(q->buffer);
321  for (rrcount = 0; rrcount < count; rrcount++) {
322  if (!buffer_skip_rr(q->buffer, 1)) {
323  ods_log_error("[%s] dropped packet: zone %s received bad notify "
324  "(bad question section)", query_str, q->zone->name);
325  return QUERY_DISCARDED;
326  }
327  }
328  pos = buffer_position(q->buffer);
329 
330  /* examine answer section */
331  count = buffer_pkt_ancount(q->buffer);
332  if (count) {
333  if (!buffer_skip_dname(q->buffer) ||
334  !query_parse_soa(q->buffer, &serial)) {
335  ods_log_error("[%s] dropped packet: zone %s received bad notify "
336  "(bad soa in answer section)", query_str, q->zone->name);
337  return QUERY_DISCARDED;
338  }
340  q->zone->xfrd->serial_notify = serial;
343  q->zone->xfrd->serial_disk)) {
344  ods_log_debug("[%s] ignore notify: already got zone %s serial "
345  "%u on disk", query_str, q->zone->name,
346  q->zone->xfrd->serial_notify);
348  goto send_notify_ok;
349  }
351  } else {
353  q->zone->xfrd->serial_notify = 0;
356  }
357  /* forward notify to xfrd */
361 
362 send_notify_ok:
363  /* send notify ok */
367 
368  buffer_clear(q->buffer); /* lim = pos, pos = 0; */
369  buffer_set_position(q->buffer, pos);
373  return QUERY_PROCESSED;
374 }
375 
376 
381 static query_state
382 query_process_ixfr(query_type* q)
383 {
384  uint16_t count = 0;
385  ods_log_assert(q);
388  /* skip header and question section */
390  if (!buffer_skip_rr(q->buffer, 1)) {
391  ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
392  "request (bad question section)", query_str, q->zone->name);
393  return QUERY_DISCARDED;
394  }
395  /* answer section is empty */
397  /* examine auth section */
399  count = buffer_pkt_nscount(q->buffer);
400  if (count) {
401  if (!buffer_skip_dname(q->buffer) ||
402  !query_parse_soa(q->buffer, &(q->serial))) {
403  ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
404  "request (bad soa in auth section)", query_str, q->zone->name);
405  return QUERY_DISCARDED;
406  }
407  ods_log_debug("[%s] found ixfr request zone %s serial=%u", query_str,
408  q->zone->name, q->serial);
409  return QUERY_PROCESSED;
410  }
411  ods_log_debug("[%s] ixfr request zone %s has no auth section", query_str,
412  q->zone->name);
413  q->serial = 0;
414  return QUERY_PROCESSED;
415 }
416 
417 
422 static int
423 response_add_rrset(response_type* r, rrset_type* rrset,
424  ldns_pkt_section section)
425 {
426  if (!r || !rrset || !section) {
427  return 0;
428  }
429  /* duplicates? */
430  r->sections[r->rrset_count] = section;
431  r->rrsets[r->rrset_count] = rrset;
432  ++r->rrset_count;
433  return 1;
434 }
435 
436 
441 static int
442 response_encode_rr(query_type* q, ldns_rr* rr, ldns_pkt_section section)
443 {
444  uint8_t *data = NULL;
445  size_t size = 0;
446  ldns_status status = LDNS_STATUS_OK;
447  ods_log_assert(q);
448  ods_log_assert(rr);
449  ods_log_assert(section);
450  status = ldns_rr2wire(&data, rr, section, &size);
451  if (status != LDNS_STATUS_OK) {
452  ods_log_error("[%s] unable to send good response: ldns_rr2wire() "
453  "failed (%s)", query_str, ldns_get_errorstr_by_id(status));
454  return 0;
455  }
456  buffer_write(q->buffer, (const void*) data, size);
457  LDNS_FREE(data);
458  return 1;
459 }
460 
461 
466 static uint16_t
467 response_encode_rrset(query_type* q, rrset_type* rrset, ldns_pkt_section section)
468 {
469  uint16_t i = 0;
470  uint16_t added = 0;
471  ods_log_assert(q);
472  ods_log_assert(rrset);
473  ods_log_assert(section);
474 
475  for (i = 0; i < rrset->rr_count; i++) {
476  added += response_encode_rr(q, rrset->rrs[i].rr, section);
477  }
478  if (q->edns_rr && q->edns_rr->dnssec_ok) {
479  for (i = 0; i < rrset->rrsig_count; i++) {
480  added += response_encode_rr(q, rrset->rrsigs[i].rr, section);
481  }
482  }
483  /* truncation? */
484  return added;
485 }
486 
487 
492 static void
493 response_encode(query_type* q, response_type* r)
494 {
495  uint16_t counts[LDNS_SECTION_ANY];
496  ldns_pkt_section s = LDNS_SECTION_QUESTION;
497  size_t i = 0;
498  ods_log_assert(q);
499  ods_log_assert(r);
500  for (s = LDNS_SECTION_ANSWER; s < LDNS_SECTION_ANY; s++) {
501  counts[s] = 0;
502  }
503  for (s = LDNS_SECTION_ANSWER; s < LDNS_SECTION_ANY; s++) {
504  for (i = 0; i < r->rrset_count; i++) {
505  if (r->sections[i] == s) {
506  counts[s] += response_encode_rrset(q, r->rrsets[i], s);
507  }
508  }
509  }
510  buffer_pkt_set_ancount(q->buffer, counts[LDNS_SECTION_ANSWER]);
511  buffer_pkt_set_nscount(q->buffer, counts[LDNS_SECTION_AUTHORITY]);
512  buffer_pkt_set_arcount(q->buffer, counts[LDNS_SECTION_ADDITIONAL]);
515  return;
516 }
517 
518 
523 static query_state
524 query_response(query_type* q, ldns_rr_type qtype)
525 {
526  rrset_type* rrset = NULL;
527  response_type r;
528  if (!q || !q->zone) {
529  return QUERY_DISCARDED;
530  }
531  r.rrset_count = 0;
533  rrset = zone_lookup_rrset(q->zone, q->zone->apex, qtype);
534  if (rrset) {
535  if (!response_add_rrset(&r, rrset, LDNS_SECTION_ANSWER)) {
537  return query_servfail(q);
538  }
539  /* NS RRset goes into Authority Section */
540  rrset = zone_lookup_rrset(q->zone, q->zone->apex, LDNS_RR_TYPE_NS);
541  if (rrset) {
542  if (!response_add_rrset(&r, rrset, LDNS_SECTION_AUTHORITY)) {
544  return query_servfail(q);
545  }
546  }
547  } else if (qtype != LDNS_RR_TYPE_SOA) {
548  rrset = zone_lookup_rrset(q->zone, q->zone->apex, LDNS_RR_TYPE_SOA);
549  if (rrset) {
550  if (!response_add_rrset(&r, rrset, LDNS_SECTION_AUTHORITY)) {
552  return query_servfail(q);
553  }
554  }
555  } else {
557  return query_servfail(q);
558  }
560 
561  response_encode(q, &r);
562  /* compression */
563  return QUERY_PROCESSED;
564 }
565 
566 
571 void
573 {
574  uint16_t limit = 0;
575  uint16_t flags = 0;
576  ods_log_assert(q);
578  limit = buffer_limit(q->buffer);
579  flags = buffer_pkt_flags(q->buffer);
580  flags &= 0x0100U; /* preserve the rd flag */
581  flags |= 0x8000U; /* set the qr flag */
582  buffer_pkt_set_flags(q->buffer, flags);
583  buffer_clear(q->buffer);
584  buffer_set_position(q->buffer, limit);
588  return;
589 }
590 
591 
596 static query_state
597 query_process_query(query_type* q, ldns_rr_type qtype, engine_type* engine)
598 {
599  dnsout_type* dnsout = NULL;
600  if (!q || !q->zone) {
601  return QUERY_DISCARDED;
602  }
603  ods_log_assert(q->zone->name);
604  ods_log_debug("[%s] incoming query qtype=%s for zone %s", query_str,
605  rrset_type2str(qtype), q->zone->name);
606  /* sanity checks */
607  if (buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_tc(q->buffer)) {
609  return query_formerr(q);
610  }
611  if (buffer_pkt_ancount(q->buffer) != 0 ||
612  (qtype != LDNS_RR_TYPE_IXFR && buffer_pkt_nscount(q->buffer) != 0)) {
614  return query_formerr(q);
615  }
616  /* acl */
617  if (!q->zone->adoutbound || q->zone->adoutbound->type != ADAPTER_DNS) {
618  ods_log_error("[%s] zone %s is not configured to have output dns "
619  "adapter", query_str, q->zone->name);
620  return query_refused(q);
621  }
623  dnsout = (dnsout_type*) q->zone->adoutbound->config;
624  /* acl also in use for soa and other queries */
625  if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) {
626  return query_refused(q);
627  }
628  /* ixfr? */
629  if (qtype == LDNS_RR_TYPE_IXFR) {
630  if (query_process_ixfr(q) != QUERY_PROCESSED) {
632  return query_formerr(q);
633  }
634  query_prepare(q);
635  ods_log_assert(q->zone->name);
636  ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s",
637  query_str, q->serial, q->zone->name);
638  return ixfr(q, engine);
639  }
640 
641  query_prepare(q);
642  /* axfr? */
643  if (qtype == LDNS_RR_TYPE_AXFR) {
644  ods_log_assert(q->zone->name);
645  ods_log_debug("[%s] incoming axfr request for zone %s",
646  query_str, q->zone->name);
647  return axfr(q, engine);
648  }
649  /* (soa) query */
650  return query_response(q, qtype);
651 }
652 
653 
658 static query_state
659 query_process_update(query_type* q)
660 {
661  if (!q || !q->zone) {
662  return QUERY_DISCARDED;
663  }
664  ods_log_debug("[%s] dynamic update not implemented", query_str);
665  return query_notimpl(q);
666 }
667 
668 
673 static ldns_pkt_rcode
674 query_process_tsig(query_type* q)
675 {
676  if (!q || !q->tsig_rr) {
677  return LDNS_RCODE_SERVFAIL;
678  }
679  if (q->tsig_rr->status == TSIG_ERROR) {
680  return LDNS_RCODE_FORMERR;
681  }
682  if (q->tsig_rr->status == TSIG_OK) {
683  if (!tsig_rr_lookup(q->tsig_rr)) {
684  ods_log_debug("[%s] tsig unknown key/algorithm", query_str);
685  return LDNS_RCODE_REFUSED;
686  }
691  if (!tsig_rr_verify(q->tsig_rr)) {
692  ods_log_debug("[%s] bad tsig signature", query_str);
693  return LDNS_RCODE_NOTAUTH;
694  }
695  }
696  return LDNS_RCODE_NOERROR;
697 }
698 
699 
704 static ldns_pkt_rcode
705 query_process_edns(query_type* q)
706 {
707  if (!q || !q->edns_rr) {
708  return LDNS_RCODE_SERVFAIL;
709  }
710  if (q->edns_rr->status == EDNS_ERROR) {
711  /* The only error is VERSION not implemented */
712  return LDNS_RCODE_FORMERR;
713  }
714  if (q->edns_rr->status == EDNS_OK) {
715  /* Only care about UDP size larger than normal... */
716  if (!q->tcp && q->edns_rr->maxlen > UDP_MAX_MESSAGE_LEN) {
717  if (q->edns_rr->maxlen < EDNS_MAX_MESSAGE_LEN) {
718  q->maxlen = q->edns_rr->maxlen;
719  } else {
721  }
722  }
723  /* Strip the OPT resource record off... */
727  }
728  return LDNS_RCODE_NOERROR;
729 }
730 
731 
736 static int
737 query_find_tsig(query_type* q)
738 {
739  size_t saved_pos = 0;
740  size_t rrcount = 0;
741  size_t i = 0;
742 
743  ods_log_assert(q);
746  if (buffer_pkt_arcount(q->buffer) == 0) {
748  return 1;
749  }
750  saved_pos = buffer_position(q->buffer);
751  rrcount = buffer_pkt_qdcount(q->buffer) + buffer_pkt_ancount(q->buffer) +
754  for (i=0; i < rrcount; i++) {
755  if (!buffer_skip_rr(q->buffer, i < buffer_pkt_qdcount(q->buffer))) {
756  buffer_set_position(q->buffer, saved_pos);
757  return 0;
758  }
759  }
760 
761  rrcount = buffer_pkt_arcount(q->buffer);
762  ods_log_assert(rrcount != 0);
763  if (!tsig_rr_parse(q->tsig_rr, q->buffer)) {
764  ods_log_debug("[%s] got bad tsig", query_str);
765  return 0;
766  }
767  if (q->tsig_rr->status != TSIG_NOT_PRESENT) {
768  --rrcount;
769  }
770  if (rrcount) {
771  if (edns_rr_parse(q->edns_rr, q->buffer)) {
772  --rrcount;
773  }
774  }
775  if (rrcount && q->tsig_rr->status == TSIG_NOT_PRESENT) {
776  /* see if tsig is after the edns record */
777  if (!tsig_rr_parse(q->tsig_rr, q->buffer)) {
778  ods_log_debug("[%s] got bad tsig", query_str);
779  return 0;
780  }
781  if (q->tsig_rr->status != TSIG_NOT_PRESENT) {
782  --rrcount;
783  }
784  }
785  if (rrcount > 0) {
786  ods_log_debug("[%s] too many additional rrs", query_str);
787  return 0;
788  }
789  buffer_set_position(q->buffer, saved_pos);
790  return 1;
791 }
792 
793 
799 query_process(query_type* q, void* engine)
800 {
801  ldns_status status = LDNS_STATUS_OK;
802  ldns_pkt* pkt = NULL;
803  ldns_rr* rr = NULL;
804  ldns_pkt_rcode rcode = LDNS_RCODE_NOERROR;
805  ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
806  ldns_rr_type qtype = LDNS_RR_TYPE_SOA;
807  engine_type* e = (engine_type*) engine;
808  ods_log_assert(e);
809  ods_log_assert(q);
811  if (!e || !q || !q->buffer) {
812  ods_log_error("[%s] drop query: assertion error", query_str);
813  return QUERY_DISCARDED; /* should not happen */
814  }
816  ods_log_debug("[%s] drop query: packet too small", query_str);
817  return QUERY_DISCARDED; /* too small */
818  }
819  if (buffer_pkt_qr(q->buffer)) {
820  ods_log_debug("[%s] drop query: qr bit set", query_str);
821  return QUERY_DISCARDED; /* not a query */
822  }
823  /* parse packet */
824  status = ldns_wire2pkt(&pkt, buffer_current(q->buffer),
826  if (status != LDNS_STATUS_OK) {
827  ods_log_debug("[%s] got bad packet: %s", query_str,
828  ldns_get_errorstr_by_id(status));
829  return query_formerr(q);
830  }
831  rr = ldns_rr_list_rr(ldns_pkt_question(pkt), 0);
833  /* we can just lookup the zone, because we will only handle SOA queries,
834  zone transfers, updates and notifies */
835  q->zone = zonelist_lookup_zone_by_dname(e->zonelist, ldns_rr_owner(rr),
836  ldns_rr_get_class(rr));
837  /* don't answer for zones that are just added */
838  if (q->zone && q->zone->zl_status == ZONE_ZL_ADDED) {
839  ods_log_warning("[%s] zone %s just added, don't answer for now",
840  query_str, q->zone->name);
841  q->zone = NULL;
842  }
844  if (!q->zone) {
845  ods_log_debug("[%s] zone not found", query_str);
846  return query_servfail(q);
847  }
848  /* see if it is tsig signed */
849  if (!query_find_tsig(q)) {
850  return query_formerr(q);
851  }
852  /* else: valid tsig, or no tsig present */
853  ods_log_debug("[%s] tsig %s", query_str, tsig_status2str(q->tsig_rr->status));
854  rcode = query_process_tsig(q);
855  if (rcode != LDNS_RCODE_NOERROR) {
856  return query_error(q, rcode);
857  }
858  /* process edns */
859  rcode = query_process_edns(q);
860  if (rcode != LDNS_RCODE_NOERROR) {
861  /* We should not return FORMERR, but BADVERS (=16).
862  * BADVERS is created with Ext. RCODE, followed by RCODE.
863  * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16).
864  * Thus RCODE = NOERROR = NSD_RC_OK. */
865  return query_error(q, LDNS_RCODE_NOERROR);
866  }
867 
868  /* handle incoming request */
869  opcode = ldns_pkt_get_opcode(pkt);
870  qtype = ldns_rr_get_type(rr);
871  ldns_pkt_free(pkt);
872 
873  switch (opcode) {
874  case LDNS_PACKET_NOTIFY:
875  return query_process_notify(q, qtype, engine);
876  case LDNS_PACKET_QUERY:
877  return query_process_query(q, qtype, engine);
878  case LDNS_PACKET_UPDATE:
879  return query_process_update(q);
880  default:
881  break;
882  }
883  return query_notimpl(q);
884 }
885 
886 
891 static int
892 query_overflow(query_type* q)
893 {
894  ods_log_assert(q);
896  return buffer_position(q->buffer) > (q->maxlen - q->reserved_space);
897 }
898 
899 
904 void
906 {
907  engine_type* e = (engine_type*) engine;
908  edns_data_type* edns = NULL;
909  if (!q || !e) {
910  return;
911  }
913  if (q->edns_rr) {
914  edns = &e->edns;
915  switch (q->edns_rr->status) {
916  case EDNS_NOT_PRESENT:
917  break;
918  case EDNS_OK:
919  ods_log_debug("[%s] add edns opt ok", query_str);
920  if (q->edns_rr->dnssec_ok) {
921  edns->ok[7] = 0x80;
922  } else {
923  edns->ok[7] = 0x00;
924  }
925  buffer_write(q->buffer, edns->ok, OPT_LEN);
926  /* fill with NULLs */
929  buffer_pkt_arcount(q->buffer) + 1);
930  break;
931  case EDNS_ERROR:
932  ods_log_debug("[%s] add edns opt err", query_str);
933  if (q->edns_rr->dnssec_ok) {
934  edns->ok[7] = 0x80;
935  } else {
936  edns->ok[7] = 0x00;
937  }
938  buffer_write(q->buffer, edns->error, OPT_LEN);
941  buffer_pkt_arcount(q->buffer) + 1);
942  break;
943  default:
944  break;
945  }
946  }
947 
949  if (!q->tsig_rr) {
950  return;
951  }
952  if (q->tsig_rr->status != TSIG_NOT_PRESENT) {
953 
954  if (q->tsig_rr->status == TSIG_ERROR ||
955  q->tsig_rr->error_code != LDNS_RCODE_NOERROR) {
956  ods_log_debug("[%s] add tsig err", query_str);
958  tsig_rr_append(q->tsig_rr, q->buffer);
960  buffer_pkt_arcount(q->buffer)+1);
961  } else if (q->tsig_rr->status == TSIG_OK &&
962  q->tsig_rr->error_code == LDNS_RCODE_NOERROR) {
963  ods_log_debug("[%s] add tsig ok", query_str);
964  if (q->tsig_prepare_it)
966  if (q->tsig_update_it)
968  buffer_position(q->buffer));
969  if (q->tsig_sign_it) {
970  tsig_rr_sign(q->tsig_rr);
971  tsig_rr_append(q->tsig_rr, q->buffer);
973  buffer_pkt_arcount(q->buffer)+1);
974  }
975  }
976  }
977  return;
978 }
979 
980 
985 int
986 query_add_rr(query_type* q, ldns_rr* rr)
987 {
988  size_t i = 0;
989  size_t tc_mark = 0;
990  size_t rdlength_pos = 0;
991  uint16_t rdlength = 0;
992 
993  ods_log_assert(q);
995  ods_log_assert(rr);
996 
997  /* set truncation mark, in case rr does not fit */
998  tc_mark = buffer_position(q->buffer);
999  /* owner type class ttl */
1000  if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
1001  goto query_add_rr_tc;
1002  }
1003  buffer_write_rdf(q->buffer, ldns_rr_owner(rr));
1004  if (!buffer_available(q->buffer, sizeof(uint16_t) + sizeof(uint16_t) +
1005  sizeof(uint32_t) + sizeof(rdlength))) {
1006  goto query_add_rr_tc;
1007  }
1008  buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_type(rr));
1009  buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_class(rr));
1010  buffer_write_u32(q->buffer, (uint32_t) ldns_rr_ttl(rr));
1011  /* skip rdlength */
1012  rdlength_pos = buffer_position(q->buffer);
1013  buffer_skip(q->buffer, sizeof(rdlength));
1014  /* write rdata */
1015  for (i=0; i < ldns_rr_rd_count(rr); i++) {
1016  if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
1017  goto query_add_rr_tc;
1018  }
1019  buffer_write_rdf(q->buffer, ldns_rr_rdf(rr, i));
1020  }
1021 
1022  if (!query_overflow(q)) {
1023  /* write rdlength */
1024  rdlength = buffer_position(q->buffer) - rdlength_pos - sizeof(rdlength);
1025  buffer_write_u16_at(q->buffer, rdlength_pos, rdlength);
1026  /* position updated by buffer_write() */
1027  return 1;
1028  }
1029 
1030 query_add_rr_tc:
1031  buffer_set_position(q->buffer, tc_mark);
1032  ods_log_assert(!query_overflow(q));
1033  return 0;
1034 
1035 }
1036 
1037 
1042 void
1044 {
1045  allocator_type* allocator = NULL;
1046  if (!q) {
1047  return;
1048  }
1049  allocator = q->allocator;
1050  buffer_cleanup(q->buffer, allocator);
1052  allocator_deallocate(allocator, (void*)q);
1053  allocator_cleanup(allocator);
1054  return;
1055 }