Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : DNS server handler for queries
5 :
6 : Copyright (C) 2010 Kai Blin <kai@samba.org>
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "samba/service_task.h"
24 : #include "libcli/util/werror.h"
25 : #include "librpc/ndr/libndr.h"
26 : #include "librpc/gen_ndr/ndr_dns.h"
27 : #include "librpc/gen_ndr/ndr_dnsp.h"
28 : #include <ldb.h>
29 : #include "param/param.h"
30 : #include "dsdb/samdb/samdb.h"
31 : #include "dsdb/common/util.h"
32 : #include "dns_server/dns_server.h"
33 : #include "libcli/dns/libdns.h"
34 : #include "lib/util/dlinklist.h"
35 : #include "lib/util/util_net.h"
36 : #include "lib/util/tevent_werror.h"
37 : #include "auth/auth.h"
38 : #include "auth/credentials/credentials.h"
39 : #include "auth/gensec/gensec.h"
40 :
41 : #undef DBGC_CLASS
42 : #define DBGC_CLASS DBGC_DNS
43 : #define MAX_Q_RECURSION_DEPTH 20
44 :
45 : struct forwarder_string {
46 : const char *forwarder;
47 : struct forwarder_string *prev, *next;
48 : };
49 :
50 5469 : static WERROR add_response_rr(const char *name,
51 : const struct dnsp_DnssrvRpcRecord *rec,
52 : struct dns_res_rec **answers)
53 : {
54 5469 : struct dns_res_rec *ans = *answers;
55 5469 : uint16_t ai = talloc_array_length(ans);
56 0 : enum ndr_err_code ndr_err;
57 :
58 5469 : if (ai == UINT16_MAX) {
59 0 : return WERR_BUFFER_OVERFLOW;
60 : }
61 :
62 : /*
63 : * "ans" is always non-NULL and thus its own talloc context
64 : */
65 5469 : ans = talloc_realloc(ans, ans, struct dns_res_rec, ai+1);
66 5469 : if (ans == NULL) {
67 0 : return WERR_NOT_ENOUGH_MEMORY;
68 : }
69 :
70 5469 : ZERO_STRUCT(ans[ai]);
71 :
72 5469 : switch (rec->wType) {
73 79 : case DNS_QTYPE_CNAME:
74 79 : ans[ai].rdata.cname_record = talloc_strdup(ans, rec->data.cname);
75 79 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.cname_record);
76 79 : break;
77 765 : case DNS_QTYPE_A:
78 765 : ans[ai].rdata.ipv4_record = talloc_strdup(ans, rec->data.ipv4);
79 765 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv4_record);
80 765 : break;
81 636 : case DNS_QTYPE_AAAA:
82 636 : ans[ai].rdata.ipv6_record = talloc_strdup(ans, rec->data.ipv6);
83 636 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv6_record);
84 636 : break;
85 75 : case DNS_TYPE_NS:
86 75 : ans[ai].rdata.ns_record = talloc_strdup(ans, rec->data.ns);
87 75 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ns_record);
88 75 : break;
89 990 : case DNS_QTYPE_SRV:
90 990 : ans[ai].rdata.srv_record.priority = rec->data.srv.wPriority;
91 990 : ans[ai].rdata.srv_record.weight = rec->data.srv.wWeight;
92 990 : ans[ai].rdata.srv_record.port = rec->data.srv.wPort;
93 1980 : ans[ai].rdata.srv_record.target = talloc_strdup(
94 990 : ans, rec->data.srv.nameTarget);
95 990 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.srv_record.target);
96 990 : break;
97 2629 : case DNS_QTYPE_SOA:
98 5258 : ans[ai].rdata.soa_record.mname = talloc_strdup(
99 2629 : ans, rec->data.soa.mname);
100 2629 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.mname);
101 5258 : ans[ai].rdata.soa_record.rname = talloc_strdup(
102 2629 : ans, rec->data.soa.rname);
103 2629 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.rname);
104 2629 : ans[ai].rdata.soa_record.serial = rec->data.soa.serial;
105 2629 : ans[ai].rdata.soa_record.refresh = rec->data.soa.refresh;
106 2629 : ans[ai].rdata.soa_record.retry = rec->data.soa.retry;
107 2629 : ans[ai].rdata.soa_record.expire = rec->data.soa.expire;
108 2629 : ans[ai].rdata.soa_record.minimum = rec->data.soa.minimum;
109 2629 : break;
110 0 : case DNS_QTYPE_PTR:
111 0 : ans[ai].rdata.ptr_record = talloc_strdup(ans, rec->data.ptr);
112 0 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ptr_record);
113 0 : break;
114 2 : case DNS_QTYPE_MX:
115 2 : ans[ai].rdata.mx_record.preference = rec->data.mx.wPriority;
116 4 : ans[ai].rdata.mx_record.exchange = talloc_strdup(
117 2 : ans, rec->data.mx.nameTarget);
118 2 : if (ans[ai].rdata.mx_record.exchange == NULL) {
119 0 : return WERR_NOT_ENOUGH_MEMORY;
120 : }
121 2 : break;
122 293 : case DNS_QTYPE_TXT:
123 293 : ndr_err = ndr_dnsp_string_list_copy(ans,
124 : &rec->data.txt,
125 293 : &ans[ai].rdata.txt_record.txt);
126 293 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
127 0 : return WERR_NOT_ENOUGH_MEMORY;
128 : }
129 293 : break;
130 0 : default:
131 0 : DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
132 0 : return DNS_ERR(NOT_IMPLEMENTED);
133 : }
134 :
135 5469 : ans[ai].name = talloc_strdup(ans, name);
136 5469 : W_ERROR_HAVE_NO_MEMORY(ans[ai].name);
137 5469 : ans[ai].rr_type = (enum dns_qtype)rec->wType;
138 5469 : ans[ai].rr_class = DNS_QCLASS_IN;
139 5469 : ans[ai].ttl = rec->dwTtlSeconds;
140 5469 : ans[ai].length = UINT16_MAX;
141 :
142 5469 : *answers = ans;
143 :
144 5469 : return WERR_OK;
145 : }
146 :
147 8 : static WERROR add_dns_res_rec(struct dns_res_rec **pdst,
148 : const struct dns_res_rec *src)
149 : {
150 8 : struct dns_res_rec *dst = *pdst;
151 8 : uint16_t di = talloc_array_length(dst);
152 0 : enum ndr_err_code ndr_err;
153 :
154 8 : if (di == UINT16_MAX) {
155 0 : return WERR_BUFFER_OVERFLOW;
156 : }
157 :
158 8 : dst = talloc_realloc(dst, dst, struct dns_res_rec, di+1);
159 8 : if (dst == NULL) {
160 0 : return WERR_NOT_ENOUGH_MEMORY;
161 : }
162 :
163 8 : ZERO_STRUCT(dst[di]);
164 :
165 16 : dst[di] = (struct dns_res_rec) {
166 8 : .name = talloc_strdup(dst, src->name),
167 8 : .rr_type = src->rr_type,
168 8 : .rr_class = src->rr_class,
169 8 : .ttl = src->ttl,
170 8 : .length = src->length
171 : };
172 :
173 8 : if (dst[di].name == NULL) {
174 0 : return WERR_NOT_ENOUGH_MEMORY;
175 : }
176 :
177 8 : switch (src->rr_type) {
178 8 : case DNS_QTYPE_CNAME:
179 16 : dst[di].rdata.cname_record = talloc_strdup(
180 8 : dst, src->rdata.cname_record);
181 8 : if (dst[di].rdata.cname_record == NULL) {
182 0 : return WERR_NOT_ENOUGH_MEMORY;
183 : }
184 8 : break;
185 0 : case DNS_QTYPE_A:
186 0 : dst[di].rdata.ipv4_record = talloc_strdup(
187 0 : dst, src->rdata.ipv4_record);
188 0 : if (dst[di].rdata.ipv4_record == NULL) {
189 0 : return WERR_NOT_ENOUGH_MEMORY;
190 : }
191 0 : break;
192 0 : case DNS_QTYPE_AAAA:
193 0 : dst[di].rdata.ipv6_record = talloc_strdup(
194 0 : dst, src->rdata.ipv6_record);
195 0 : if (dst[di].rdata.ipv6_record == NULL) {
196 0 : return WERR_NOT_ENOUGH_MEMORY;
197 : }
198 0 : break;
199 0 : case DNS_TYPE_NS:
200 0 : dst[di].rdata.ns_record = talloc_strdup(
201 0 : dst, src->rdata.ns_record);
202 0 : if (dst[di].rdata.ns_record == NULL) {
203 0 : return WERR_NOT_ENOUGH_MEMORY;
204 : }
205 0 : break;
206 0 : case DNS_QTYPE_SRV:
207 0 : dst[di].rdata.srv_record = (struct dns_srv_record) {
208 0 : .priority = src->rdata.srv_record.priority,
209 0 : .weight = src->rdata.srv_record.weight,
210 0 : .port = src->rdata.srv_record.port,
211 0 : .target = talloc_strdup(
212 0 : dst, src->rdata.srv_record.target)
213 : };
214 0 : if (dst[di].rdata.srv_record.target == NULL) {
215 0 : return WERR_NOT_ENOUGH_MEMORY;
216 : }
217 0 : break;
218 0 : case DNS_QTYPE_SOA:
219 0 : dst[di].rdata.soa_record = (struct dns_soa_record) {
220 0 : .mname = talloc_strdup(
221 0 : dst, src->rdata.soa_record.mname),
222 0 : .rname = talloc_strdup(
223 0 : dst, src->rdata.soa_record.rname),
224 0 : .serial = src->rdata.soa_record.serial,
225 0 : .refresh = src->rdata.soa_record.refresh,
226 0 : .retry = src->rdata.soa_record.retry,
227 0 : .expire = src->rdata.soa_record.expire,
228 0 : .minimum = src->rdata.soa_record.minimum
229 : };
230 :
231 0 : if ((dst[di].rdata.soa_record.mname == NULL) ||
232 0 : (dst[di].rdata.soa_record.rname == NULL)) {
233 0 : return WERR_NOT_ENOUGH_MEMORY;
234 : }
235 :
236 0 : break;
237 0 : case DNS_QTYPE_PTR:
238 0 : dst[di].rdata.ptr_record = talloc_strdup(
239 0 : dst, src->rdata.ptr_record);
240 0 : if (dst[di].rdata.ptr_record == NULL) {
241 0 : return WERR_NOT_ENOUGH_MEMORY;
242 : }
243 0 : break;
244 0 : case DNS_QTYPE_MX:
245 0 : dst[di].rdata.mx_record = (struct dns_mx_record) {
246 0 : .preference = src->rdata.mx_record.preference,
247 0 : .exchange = talloc_strdup(
248 0 : src, src->rdata.mx_record.exchange)
249 : };
250 :
251 0 : if (dst[di].rdata.mx_record.exchange == NULL) {
252 0 : return WERR_NOT_ENOUGH_MEMORY;
253 : }
254 0 : break;
255 0 : case DNS_QTYPE_TXT:
256 0 : ndr_err = ndr_dnsp_string_list_copy(dst,
257 : &src->rdata.txt_record.txt,
258 0 : &dst[di].rdata.txt_record.txt);
259 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
260 0 : return WERR_NOT_ENOUGH_MEMORY;
261 : }
262 0 : break;
263 0 : default:
264 0 : DBG_WARNING("Got unhandled type %u query.\n", src->rr_type);
265 0 : return DNS_ERR(NOT_IMPLEMENTED);
266 : }
267 :
268 8 : *pdst = dst;
269 :
270 8 : return WERR_OK;
271 : }
272 :
273 : struct ask_forwarder_state {
274 : struct dns_name_packet *reply;
275 : };
276 :
277 : static void ask_forwarder_done(struct tevent_req *subreq);
278 :
279 38 : static struct tevent_req *ask_forwarder_send(
280 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
281 : const char *forwarder, struct dns_name_question *question)
282 : {
283 0 : struct tevent_req *req, *subreq;
284 0 : struct ask_forwarder_state *state;
285 :
286 38 : req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state);
287 38 : if (req == NULL) {
288 0 : return NULL;
289 : }
290 :
291 38 : subreq = dns_cli_request_send(state, ev, forwarder,
292 : question->name, question->question_class,
293 : question->question_type);
294 38 : if (tevent_req_nomem(subreq, req)) {
295 0 : return tevent_req_post(req, ev);
296 : }
297 38 : tevent_req_set_callback(subreq, ask_forwarder_done, req);
298 38 : return req;
299 : }
300 :
301 38 : static void ask_forwarder_done(struct tevent_req *subreq)
302 : {
303 38 : struct tevent_req *req = tevent_req_callback_data(
304 : subreq, struct tevent_req);
305 38 : struct ask_forwarder_state *state = tevent_req_data(
306 : req, struct ask_forwarder_state);
307 0 : int ret;
308 :
309 38 : ret = dns_cli_request_recv(subreq, state, &state->reply);
310 38 : TALLOC_FREE(subreq);
311 :
312 38 : if (ret != 0) {
313 20 : tevent_req_werror(req, unix_to_werror(ret));
314 20 : return;
315 : }
316 :
317 18 : tevent_req_done(req);
318 : }
319 :
320 38 : static WERROR ask_forwarder_recv(
321 : struct tevent_req *req, TALLOC_CTX *mem_ctx,
322 : struct dns_res_rec **answers, uint16_t *ancount,
323 : struct dns_res_rec **nsrecs, uint16_t *nscount,
324 : struct dns_res_rec **additional, uint16_t *arcount)
325 : {
326 38 : struct ask_forwarder_state *state = tevent_req_data(
327 : req, struct ask_forwarder_state);
328 38 : struct dns_name_packet *in_packet = state->reply;
329 0 : WERROR err;
330 :
331 38 : if (tevent_req_is_werror(req, &err)) {
332 20 : return err;
333 : }
334 :
335 18 : *ancount = in_packet->ancount;
336 18 : *answers = talloc_move(mem_ctx, &in_packet->answers);
337 :
338 18 : *nscount = in_packet->nscount;
339 18 : *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs);
340 :
341 18 : *arcount = in_packet->arcount;
342 18 : *additional = talloc_move(mem_ctx, &in_packet->additional);
343 :
344 18 : return WERR_OK;
345 : }
346 :
347 2589 : static WERROR add_zone_authority_record(struct dns_server *dns,
348 : TALLOC_CTX *mem_ctx,
349 : const struct dns_name_question *question,
350 : struct dns_res_rec **nsrecs)
351 : {
352 2589 : const char *zone = NULL;
353 0 : struct dnsp_DnssrvRpcRecord *recs;
354 2589 : struct dns_res_rec *ns = *nsrecs;
355 0 : uint16_t rec_count;
356 2589 : struct ldb_dn *dn = NULL;
357 0 : unsigned int ri;
358 0 : WERROR werror;
359 :
360 2589 : zone = dns_get_authoritative_zone(dns, question->name);
361 2589 : DEBUG(10, ("Creating zone authority record for '%s'\n", zone));
362 :
363 2589 : werror = dns_name2dn(dns, mem_ctx, zone, &dn);
364 2589 : if (!W_ERROR_IS_OK(werror)) {
365 0 : return werror;
366 : }
367 :
368 2589 : werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count);
369 2589 : if (!W_ERROR_IS_OK(werror)) {
370 6 : return werror;
371 : }
372 :
373 12575 : for (ri = 0; ri < rec_count; ri++) {
374 9992 : if (recs[ri].wType == DNS_TYPE_SOA) {
375 2583 : werror = add_response_rr(zone, &recs[ri], &ns);
376 2583 : if (!W_ERROR_IS_OK(werror)) {
377 0 : return werror;
378 : }
379 : }
380 : }
381 :
382 2583 : *nsrecs = ns;
383 :
384 2583 : return WERR_OK;
385 : }
386 :
387 : static struct tevent_req *handle_authoritative_send(
388 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
389 : struct dns_server *dns, const char *forwarder,
390 : struct dns_name_question *question,
391 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
392 : size_t cname_depth);
393 : static WERROR handle_authoritative_recv(struct tevent_req *req);
394 :
395 : struct handle_dnsrpcrec_state {
396 : struct dns_res_rec **answers;
397 : struct dns_res_rec **nsrecs;
398 : };
399 :
400 : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq);
401 : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq);
402 :
403 4774 : static struct tevent_req *handle_dnsrpcrec_send(
404 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
405 : struct dns_server *dns, const char *forwarder,
406 : const struct dns_name_question *question,
407 : struct dnsp_DnssrvRpcRecord *rec,
408 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
409 : size_t cname_depth)
410 : {
411 0 : struct tevent_req *req, *subreq;
412 0 : struct handle_dnsrpcrec_state *state;
413 0 : struct dns_name_question *new_q;
414 0 : bool resolve_cname;
415 0 : WERROR werr;
416 :
417 4774 : req = tevent_req_create(mem_ctx, &state,
418 : struct handle_dnsrpcrec_state);
419 4774 : if (req == NULL) {
420 0 : return NULL;
421 : }
422 4774 : state->answers = answers;
423 4774 : state->nsrecs = nsrecs;
424 :
425 4774 : if (cname_depth >= MAX_Q_RECURSION_DEPTH) {
426 2 : tevent_req_done(req);
427 2 : return tevent_req_post(req, ev);
428 : }
429 :
430 4853 : resolve_cname = ((rec->wType == DNS_TYPE_CNAME) &&
431 81 : ((question->question_type == DNS_QTYPE_A) ||
432 12 : (question->question_type == DNS_QTYPE_AAAA)));
433 :
434 4772 : if (!resolve_cname) {
435 4703 : if ((question->question_type != DNS_QTYPE_ALL) &&
436 4693 : (rec->wType !=
437 4693 : (enum dns_record_type) question->question_type)) {
438 1886 : tevent_req_done(req);
439 1886 : return tevent_req_post(req, ev);
440 : }
441 :
442 2817 : werr = add_response_rr(question->name, rec, state->answers);
443 2817 : if (tevent_req_werror(req, werr)) {
444 0 : return tevent_req_post(req, ev);
445 : }
446 :
447 2817 : tevent_req_done(req);
448 2817 : return tevent_req_post(req, ev);
449 : }
450 :
451 69 : werr = add_response_rr(question->name, rec, state->answers);
452 69 : if (tevent_req_werror(req, werr)) {
453 0 : return tevent_req_post(req, ev);
454 : }
455 :
456 69 : new_q = talloc(state, struct dns_name_question);
457 69 : if (tevent_req_nomem(new_q, req)) {
458 0 : return tevent_req_post(req, ev);
459 : }
460 :
461 69 : *new_q = (struct dns_name_question) {
462 69 : .question_type = question->question_type,
463 69 : .question_class = question->question_class,
464 69 : .name = rec->data.cname
465 : };
466 :
467 69 : if (dns_authoritative_for_zone(dns, new_q->name)) {
468 57 : subreq = handle_authoritative_send(
469 : state, ev, dns, forwarder, new_q,
470 57 : state->answers, state->nsrecs,
471 : cname_depth + 1);
472 57 : if (tevent_req_nomem(subreq, req)) {
473 0 : return tevent_req_post(req, ev);
474 : }
475 57 : tevent_req_set_callback(subreq, handle_dnsrpcrec_gotauth, req);
476 57 : return req;
477 : }
478 :
479 12 : subreq = ask_forwarder_send(state, ev, forwarder, new_q);
480 12 : if (tevent_req_nomem(subreq, req)) {
481 0 : return tevent_req_post(req, ev);
482 : }
483 12 : tevent_req_set_callback(subreq, handle_dnsrpcrec_gotforwarded, req);
484 :
485 12 : return req;
486 : }
487 :
488 57 : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq)
489 : {
490 57 : struct tevent_req *req = tevent_req_callback_data(
491 : subreq, struct tevent_req);
492 0 : WERROR werr;
493 :
494 57 : werr = handle_authoritative_recv(subreq);
495 57 : TALLOC_FREE(subreq);
496 57 : if (tevent_req_werror(req, werr)) {
497 2 : return;
498 : }
499 55 : tevent_req_done(req);
500 : }
501 :
502 12 : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq)
503 : {
504 12 : struct tevent_req *req = tevent_req_callback_data(
505 : subreq, struct tevent_req);
506 12 : struct handle_dnsrpcrec_state *state = tevent_req_data(
507 : req, struct handle_dnsrpcrec_state);
508 0 : struct dns_res_rec *answers, *nsrecs, *additional;
509 12 : uint16_t ancount = 0;
510 12 : uint16_t nscount = 0;
511 12 : uint16_t arcount = 0;
512 0 : uint16_t i;
513 0 : WERROR werr;
514 :
515 12 : werr = ask_forwarder_recv(subreq, state, &answers, &ancount,
516 : &nsrecs, &nscount, &additional, &arcount);
517 12 : if (tevent_req_werror(req, werr)) {
518 4 : return;
519 : }
520 :
521 16 : for (i=0; i<ancount; i++) {
522 8 : werr = add_dns_res_rec(state->answers, &answers[i]);
523 8 : if (tevent_req_werror(req, werr)) {
524 0 : return;
525 : }
526 : }
527 :
528 8 : for (i=0; i<nscount; i++) {
529 0 : werr = add_dns_res_rec(state->nsrecs, &nsrecs[i]);
530 0 : if (tevent_req_werror(req, werr)) {
531 0 : return;
532 : }
533 : }
534 :
535 8 : tevent_req_done(req);
536 : }
537 :
538 4774 : static WERROR handle_dnsrpcrec_recv(struct tevent_req *req)
539 : {
540 4774 : return tevent_req_simple_recv_werror(req);
541 : }
542 :
543 : struct handle_authoritative_state {
544 : struct tevent_context *ev;
545 : struct dns_server *dns;
546 : struct dns_name_question *question;
547 : const char *forwarder;
548 :
549 : struct dnsp_DnssrvRpcRecord *recs;
550 : uint16_t rec_count;
551 : uint16_t recs_done;
552 :
553 : struct dns_res_rec **answers;
554 : struct dns_res_rec **nsrecs;
555 :
556 : size_t cname_depth;
557 : };
558 :
559 : static void handle_authoritative_done(struct tevent_req *subreq);
560 :
561 2684 : static struct tevent_req *handle_authoritative_send(
562 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
563 : struct dns_server *dns, const char *forwarder,
564 : struct dns_name_question *question,
565 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
566 : size_t cname_depth)
567 : {
568 0 : struct tevent_req *req, *subreq;
569 0 : struct handle_authoritative_state *state;
570 2684 : struct ldb_dn *dn = NULL;
571 0 : WERROR werr;
572 :
573 2684 : req = tevent_req_create(mem_ctx, &state,
574 : struct handle_authoritative_state);
575 2684 : if (req == NULL) {
576 0 : return NULL;
577 : }
578 2684 : state->ev = ev;
579 2684 : state->dns = dns;
580 2684 : state->question = question;
581 2684 : state->forwarder = forwarder;
582 2684 : state->answers = answers;
583 2684 : state->nsrecs = nsrecs;
584 2684 : state->cname_depth = cname_depth;
585 :
586 2684 : werr = dns_name2dn(dns, state, question->name, &dn);
587 2684 : if (tevent_req_werror(req, werr)) {
588 0 : return tevent_req_post(req, ev);
589 : }
590 2684 : werr = dns_lookup_records_wildcard(dns, state, dn, &state->recs,
591 2684 : &state->rec_count);
592 2684 : TALLOC_FREE(dn);
593 2684 : if (tevent_req_werror(req, werr)) {
594 146 : return tevent_req_post(req, ev);
595 : }
596 :
597 2538 : if (state->rec_count == 0) {
598 0 : tevent_req_werror(req, DNS_ERR(NAME_ERROR));
599 0 : return tevent_req_post(req, ev);
600 : }
601 :
602 2538 : subreq = handle_dnsrpcrec_send(
603 2538 : state, state->ev, state->dns, state->forwarder,
604 2538 : state->question, &state->recs[state->recs_done],
605 2538 : state->answers, state->nsrecs,
606 2538 : state->cname_depth);
607 2538 : if (tevent_req_nomem(subreq, req)) {
608 0 : return tevent_req_post(req, ev);
609 : }
610 2538 : tevent_req_set_callback(subreq, handle_authoritative_done, req);
611 2538 : return req;
612 : }
613 :
614 4774 : static void handle_authoritative_done(struct tevent_req *subreq)
615 : {
616 4774 : struct tevent_req *req = tevent_req_callback_data(
617 : subreq, struct tevent_req);
618 4774 : struct handle_authoritative_state *state = tevent_req_data(
619 : req, struct handle_authoritative_state);
620 0 : WERROR werr;
621 :
622 4774 : werr = handle_dnsrpcrec_recv(subreq);
623 4774 : TALLOC_FREE(subreq);
624 4774 : if (tevent_req_werror(req, werr)) {
625 2538 : return;
626 : }
627 :
628 4768 : state->recs_done += 1;
629 :
630 4768 : if (state->recs_done == state->rec_count) {
631 2532 : tevent_req_done(req);
632 2532 : return;
633 : }
634 :
635 2236 : subreq = handle_dnsrpcrec_send(
636 : state, state->ev, state->dns, state->forwarder,
637 2236 : state->question, &state->recs[state->recs_done],
638 : state->answers, state->nsrecs,
639 : state->cname_depth);
640 2236 : if (tevent_req_nomem(subreq, req)) {
641 0 : return;
642 : }
643 2236 : tevent_req_set_callback(subreq, handle_authoritative_done, req);
644 : }
645 :
646 2684 : static WERROR handle_authoritative_recv(struct tevent_req *req)
647 : {
648 0 : WERROR werr;
649 :
650 2684 : if (tevent_req_is_werror(req, &werr)) {
651 152 : return werr;
652 : }
653 :
654 2532 : return WERR_OK;
655 : }
656 :
657 68 : static NTSTATUS create_tkey(struct dns_server *dns,
658 : const char* name,
659 : const char* algorithm,
660 : const struct tsocket_address *remote_address,
661 : const struct tsocket_address *local_address,
662 : struct dns_server_tkey **tkey)
663 : {
664 0 : NTSTATUS status;
665 68 : struct dns_server_tkey_store *store = dns->tkeys;
666 68 : struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey);
667 :
668 68 : if (k == NULL) {
669 0 : return NT_STATUS_NO_MEMORY;
670 : }
671 :
672 68 : k->name = talloc_strdup(k, name);
673 :
674 68 : if (k->name == NULL) {
675 0 : return NT_STATUS_NO_MEMORY;
676 : }
677 :
678 68 : k->algorithm = talloc_strdup(k, algorithm);
679 68 : if (k->algorithm == NULL) {
680 0 : return NT_STATUS_NO_MEMORY;
681 : }
682 :
683 : /*
684 : * We only allow SPNEGO/KRB5 currently
685 : * and rely on the backend to be RPC/IPC free.
686 : *
687 : * It allows gensec_update() not to block.
688 : */
689 68 : status = samba_server_gensec_krb5_start(k,
690 68 : dns->task->event_ctx,
691 68 : dns->task->msg_ctx,
692 68 : dns->task->lp_ctx,
693 : dns->server_credentials,
694 : "dns",
695 : &k->gensec);
696 68 : if (!NT_STATUS_IS_OK(status)) {
697 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
698 0 : *tkey = NULL;
699 0 : return status;
700 : }
701 :
702 68 : gensec_want_feature(k->gensec, GENSEC_FEATURE_SIGN);
703 :
704 68 : status = gensec_set_remote_address(k->gensec,
705 : remote_address);
706 68 : if (!NT_STATUS_IS_OK(status)) {
707 0 : DEBUG(1, ("Failed to set remote address into GENSEC: %s\n",
708 : nt_errstr(status)));
709 0 : *tkey = NULL;
710 0 : return status;
711 : }
712 :
713 68 : status = gensec_set_local_address(k->gensec,
714 : local_address);
715 68 : if (!NT_STATUS_IS_OK(status)) {
716 0 : DEBUG(1, ("Failed to set local address into GENSEC: %s\n",
717 : nt_errstr(status)));
718 0 : *tkey = NULL;
719 0 : return status;
720 : }
721 :
722 68 : status = gensec_start_mech_by_oid(k->gensec, GENSEC_OID_SPNEGO);
723 :
724 68 : if (!NT_STATUS_IS_OK(status)) {
725 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n",
726 : nt_errstr(status)));
727 0 : *tkey = NULL;
728 0 : return status;
729 : }
730 :
731 68 : TALLOC_FREE(store->tkeys[store->next_idx]);
732 :
733 68 : store->tkeys[store->next_idx] = k;
734 68 : (store->next_idx)++;
735 68 : store->next_idx %= store->size;
736 :
737 68 : *tkey = k;
738 68 : return NT_STATUS_OK;
739 : }
740 :
741 68 : static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
742 : struct dns_server *dns,
743 : struct dns_server_tkey *tkey,
744 : const DATA_BLOB *key,
745 : DATA_BLOB *reply,
746 : uint16_t *dns_auth_error)
747 : {
748 0 : NTSTATUS status;
749 :
750 : /*
751 : * We use samba_server_gensec_krb5_start(),
752 : * which only allows SPNEGO/KRB5 currently
753 : * and makes sure the backend to be RPC/IPC free.
754 : *
755 : * See gensec_gssapi_update_internal() as
756 : * GENSEC_SERVER.
757 : *
758 : * It allows gensec_update() not to block.
759 : *
760 : * If that changes in future we need to use
761 : * gensec_update_send/recv here!
762 : */
763 68 : status = gensec_update(tkey->gensec, mem_ctx,
764 : *key, reply);
765 :
766 68 : if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
767 0 : *dns_auth_error = DNS_RCODE_OK;
768 0 : return status;
769 : }
770 :
771 68 : if (NT_STATUS_IS_OK(status)) {
772 :
773 68 : status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info);
774 68 : if (!NT_STATUS_IS_OK(status)) {
775 0 : *dns_auth_error = DNS_RCODE_BADKEY;
776 0 : return status;
777 : }
778 68 : *dns_auth_error = DNS_RCODE_OK;
779 : }
780 :
781 68 : return status;
782 : }
783 :
784 68 : static WERROR handle_tkey(struct dns_server *dns,
785 : TALLOC_CTX *mem_ctx,
786 : const struct dns_name_packet *in,
787 : struct dns_request_state *state,
788 : struct dns_res_rec **answers,
789 : uint16_t *ancount)
790 : {
791 68 : struct dns_res_rec *in_tkey = NULL;
792 0 : struct dns_res_rec *ret_tkey;
793 0 : uint16_t i;
794 :
795 68 : for (i = 0; i < in->arcount; i++) {
796 68 : if (in->additional[i].rr_type == DNS_QTYPE_TKEY) {
797 68 : in_tkey = &in->additional[i];
798 68 : break;
799 : }
800 : }
801 :
802 : /* If this is a TKEY query, it should have a TKEY RR.
803 : * Behaviour is not really specified in RFC 2930 or RFC 3645, but
804 : * FORMAT_ERROR seems to be what BIND uses .*/
805 68 : if (in_tkey == NULL) {
806 0 : return DNS_ERR(FORMAT_ERROR);
807 : }
808 :
809 68 : ret_tkey = talloc_zero(mem_ctx, struct dns_res_rec);
810 68 : if (ret_tkey == NULL) {
811 0 : return WERR_NOT_ENOUGH_MEMORY;
812 : }
813 :
814 68 : ret_tkey->name = talloc_strdup(ret_tkey, in_tkey->name);
815 68 : if (ret_tkey->name == NULL) {
816 0 : return WERR_NOT_ENOUGH_MEMORY;
817 : }
818 :
819 68 : ret_tkey->rr_type = DNS_QTYPE_TKEY;
820 68 : ret_tkey->rr_class = DNS_QCLASS_ANY;
821 68 : ret_tkey->length = UINT16_MAX;
822 :
823 68 : ret_tkey->rdata.tkey_record.algorithm = talloc_strdup(ret_tkey,
824 : in_tkey->rdata.tkey_record.algorithm);
825 68 : if (ret_tkey->rdata.tkey_record.algorithm == NULL) {
826 0 : return WERR_NOT_ENOUGH_MEMORY;
827 : }
828 :
829 68 : ret_tkey->rdata.tkey_record.inception = in_tkey->rdata.tkey_record.inception;
830 68 : ret_tkey->rdata.tkey_record.expiration = in_tkey->rdata.tkey_record.expiration;
831 68 : ret_tkey->rdata.tkey_record.mode = in_tkey->rdata.tkey_record.mode;
832 :
833 68 : switch (in_tkey->rdata.tkey_record.mode) {
834 0 : case DNS_TKEY_MODE_DH:
835 : /* FIXME: According to RFC 2930, we MUST support this, but we don't.
836 : * Still, claim it's a bad key instead of a bad mode */
837 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
838 0 : break;
839 68 : case DNS_TKEY_MODE_GSSAPI: {
840 0 : NTSTATUS status;
841 0 : struct dns_server_tkey *tkey;
842 0 : DATA_BLOB key;
843 0 : DATA_BLOB reply;
844 :
845 68 : tkey = dns_find_tkey(dns->tkeys, in->questions[0].name);
846 68 : if (tkey != NULL && tkey->complete) {
847 : /* TODO: check if the key is still valid */
848 0 : DEBUG(1, ("Rejecting tkey negotiation for already established key\n"));
849 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADNAME;
850 68 : break;
851 : }
852 :
853 68 : if (tkey == NULL) {
854 68 : status = create_tkey(dns, in->questions[0].name,
855 : in_tkey->rdata.tkey_record.algorithm,
856 : state->remote_address,
857 : state->local_address,
858 : &tkey);
859 68 : if (!NT_STATUS_IS_OK(status)) {
860 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
861 0 : return ntstatus_to_werror(status);
862 : }
863 : }
864 :
865 68 : key.data = in_tkey->rdata.tkey_record.key_data;
866 68 : key.length = in_tkey->rdata.tkey_record.key_size;
867 :
868 68 : status = accept_gss_ticket(ret_tkey, dns, tkey, &key, &reply,
869 : &ret_tkey->rdata.tkey_record.error);
870 68 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
871 0 : DEBUG(1, ("More processing required\n"));
872 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
873 68 : } else if (NT_STATUS_IS_OK(status)) {
874 68 : DBG_DEBUG("Tkey handshake completed\n");
875 68 : ret_tkey->rdata.tkey_record.key_size = reply.length;
876 68 : ret_tkey->rdata.tkey_record.key_data = talloc_memdup(ret_tkey,
877 : reply.data,
878 : reply.length);
879 68 : if (ret_tkey->rdata.tkey_record.key_data == NULL) {
880 0 : return WERR_NOT_ENOUGH_MEMORY;
881 : }
882 68 : state->sign = true;
883 68 : state->key_name = talloc_strdup(state->mem_ctx, tkey->name);
884 68 : if (state->key_name == NULL) {
885 0 : return WERR_NOT_ENOUGH_MEMORY;
886 : }
887 : } else {
888 0 : DEBUG(1, ("GSS key negotiation returned %s\n", nt_errstr(status)));
889 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
890 : }
891 :
892 68 : break;
893 : }
894 0 : case DNS_TKEY_MODE_DELETE:
895 : /* TODO: implement me */
896 0 : DEBUG(1, ("Should delete tkey here\n"));
897 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_OK;
898 0 : break;
899 0 : case DNS_TKEY_MODE_NULL:
900 : case DNS_TKEY_MODE_SERVER:
901 : case DNS_TKEY_MODE_CLIENT:
902 : case DNS_TKEY_MODE_LAST:
903 : /* We don't have to implement these, return a mode error */
904 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADMODE;
905 0 : break;
906 0 : default:
907 0 : DEBUG(1, ("Unsupported TKEY mode %d\n",
908 : in_tkey->rdata.tkey_record.mode));
909 : }
910 :
911 68 : *answers = ret_tkey;
912 68 : *ancount = 1;
913 :
914 68 : return WERR_OK;
915 : }
916 :
917 : struct dns_server_process_query_state {
918 : struct tevent_context *ev;
919 : struct dns_server *dns;
920 : struct dns_name_question *question;
921 :
922 : struct dns_res_rec *answers;
923 : uint16_t ancount;
924 : struct dns_res_rec *nsrecs;
925 : uint16_t nscount;
926 : struct dns_res_rec *additional;
927 : uint16_t arcount;
928 : struct forwarder_string *forwarders;
929 : };
930 :
931 : static void dns_server_process_query_got_auth(struct tevent_req *subreq);
932 : static void dns_server_process_query_got_response(struct tevent_req *subreq);
933 :
934 2688 : struct tevent_req *dns_server_process_query_send(
935 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
936 : struct dns_server *dns, struct dns_request_state *req_state,
937 : const struct dns_name_packet *in)
938 : {
939 0 : struct tevent_req *req, *subreq;
940 0 : struct dns_server_process_query_state *state;
941 2688 : const char **forwarders = NULL;
942 0 : unsigned int i;
943 :
944 2688 : req = tevent_req_create(mem_ctx, &state,
945 : struct dns_server_process_query_state);
946 2688 : if (req == NULL) {
947 0 : return NULL;
948 : }
949 2688 : if (in->qdcount != 1) {
950 4 : tevent_req_werror(req, DNS_ERR(FORMAT_ERROR));
951 4 : return tevent_req_post(req, ev);
952 : }
953 :
954 : /* Windows returns NOT_IMPLEMENTED on this as well */
955 2684 : if (in->questions[0].question_class == DNS_QCLASS_NONE) {
956 4 : tevent_req_werror(req, DNS_ERR(NOT_IMPLEMENTED));
957 4 : return tevent_req_post(req, ev);
958 : }
959 :
960 2680 : if (in->questions[0].question_type == DNS_QTYPE_TKEY) {
961 0 : WERROR err;
962 :
963 68 : err = handle_tkey(dns, state, in, req_state,
964 68 : &state->answers, &state->ancount);
965 68 : if (tevent_req_werror(req, err)) {
966 0 : return tevent_req_post(req, ev);
967 : }
968 68 : tevent_req_done(req);
969 68 : return tevent_req_post(req, ev);
970 : }
971 :
972 2612 : state->dns = dns;
973 2612 : state->ev = ev;
974 2612 : state->question = &in->questions[0];
975 :
976 2612 : forwarders = lpcfg_dns_forwarder(dns->task->lp_ctx);
977 3088 : for (i = 0; forwarders != NULL && forwarders[i] != NULL; i++) {
978 476 : struct forwarder_string *f = talloc_zero(state,
979 : struct forwarder_string);
980 476 : f->forwarder = forwarders[i];
981 476 : DLIST_ADD_END(state->forwarders, f);
982 : }
983 :
984 2612 : if (dns_authoritative_for_zone(dns, in->questions[0].name)) {
985 :
986 2589 : req_state->flags |= DNS_FLAG_AUTHORITATIVE;
987 :
988 : /*
989 : * Initialize the response arrays, so that we can use
990 : * them as their own talloc contexts when doing the
991 : * realloc
992 : */
993 2589 : state->answers = talloc_array(state, struct dns_res_rec, 0);
994 2589 : if (tevent_req_nomem(state->answers, req)) {
995 0 : return tevent_req_post(req, ev);
996 : }
997 2589 : state->nsrecs = talloc_array(state, struct dns_res_rec, 0);
998 2589 : if (tevent_req_nomem(state->nsrecs, req)) {
999 0 : return tevent_req_post(req, ev);
1000 : }
1001 :
1002 2589 : subreq = handle_authoritative_send(
1003 : state, ev, dns, (forwarders == NULL ? NULL : forwarders[0]),
1004 2589 : &in->questions[0], &state->answers, &state->nsrecs,
1005 : 0); /* cname_depth */
1006 2589 : if (tevent_req_nomem(subreq, req)) {
1007 0 : return tevent_req_post(req, ev);
1008 : }
1009 2589 : tevent_req_set_callback(
1010 : subreq, dns_server_process_query_got_auth, req);
1011 2589 : return req;
1012 : }
1013 :
1014 23 : if ((req_state->flags & DNS_FLAG_RECURSION_DESIRED) &&
1015 20 : (req_state->flags & DNS_FLAG_RECURSION_AVAIL)) {
1016 16 : DEBUG(5, ("Not authoritative for '%s', forwarding\n",
1017 : in->questions[0].name));
1018 :
1019 16 : subreq = ask_forwarder_send(state, ev,
1020 : (forwarders == NULL ? NULL : forwarders[0]),
1021 16 : &in->questions[0]);
1022 16 : if (tevent_req_nomem(subreq, req)) {
1023 0 : return tevent_req_post(req, ev);
1024 : }
1025 16 : tevent_req_set_callback(
1026 : subreq, dns_server_process_query_got_response, req);
1027 16 : return req;
1028 : }
1029 :
1030 7 : tevent_req_werror(req, DNS_ERR(NAME_ERROR));
1031 7 : return tevent_req_post(req, ev);
1032 : }
1033 :
1034 26 : static void dns_server_process_query_got_response(struct tevent_req *subreq)
1035 : {
1036 26 : struct tevent_req *req = tevent_req_callback_data(
1037 : subreq, struct tevent_req);
1038 26 : struct dns_server_process_query_state *state = tevent_req_data(
1039 : req, struct dns_server_process_query_state);
1040 0 : WERROR werr;
1041 :
1042 26 : werr = ask_forwarder_recv(subreq, state,
1043 : &state->answers, &state->ancount,
1044 : &state->nsrecs, &state->nscount,
1045 : &state->additional, &state->arcount);
1046 26 : TALLOC_FREE(subreq);
1047 :
1048 : /* If you get an error, attempt a different forwarder */
1049 26 : if (!W_ERROR_IS_OK(werr)) {
1050 16 : if (state->forwarders != NULL) {
1051 16 : DLIST_REMOVE(state->forwarders, state->forwarders);
1052 : }
1053 :
1054 : /* If you have run out of forwarders, simply finish */
1055 16 : if (state->forwarders == NULL) {
1056 6 : tevent_req_werror(req, werr);
1057 16 : return;
1058 : }
1059 :
1060 10 : DEBUG(5, ("DNS query returned %s, trying another forwarder.\n",
1061 : win_errstr(werr)));
1062 10 : subreq = ask_forwarder_send(state, state->ev,
1063 10 : state->forwarders->forwarder,
1064 : state->question);
1065 :
1066 10 : if (tevent_req_nomem(subreq, req)) {
1067 0 : return;
1068 : }
1069 :
1070 10 : tevent_req_set_callback(subreq,
1071 : dns_server_process_query_got_response,
1072 : req);
1073 10 : return;
1074 : }
1075 :
1076 10 : tevent_req_done(req);
1077 : }
1078 :
1079 2627 : static void dns_server_process_query_got_auth(struct tevent_req *subreq)
1080 : {
1081 2627 : struct tevent_req *req = tevent_req_callback_data(
1082 : subreq, struct tevent_req);
1083 2627 : struct dns_server_process_query_state *state = tevent_req_data(
1084 : req, struct dns_server_process_query_state);
1085 0 : WERROR werr;
1086 0 : WERROR werr2;
1087 :
1088 2627 : werr = handle_authoritative_recv(subreq);
1089 2627 : TALLOC_FREE(subreq);
1090 :
1091 : /* If you get an error, attempt a different forwarder */
1092 2627 : if (!W_ERROR_IS_OK(werr)) {
1093 150 : if (state->forwarders != NULL) {
1094 72 : DLIST_REMOVE(state->forwarders, state->forwarders);
1095 : }
1096 :
1097 : /* If you have run out of forwarders, simply finish */
1098 150 : if (state->forwarders == NULL) {
1099 112 : werr2 = add_zone_authority_record(state->dns,
1100 : state,
1101 112 : state->question,
1102 : &state->nsrecs);
1103 112 : if (tevent_req_werror(req, werr2)) {
1104 6 : DBG_WARNING("Failed to add SOA record: %s\n",
1105 : win_errstr(werr2));
1106 150 : return;
1107 : }
1108 :
1109 106 : state->ancount = talloc_array_length(state->answers);
1110 106 : state->nscount = talloc_array_length(state->nsrecs);
1111 106 : state->arcount = talloc_array_length(state->additional);
1112 :
1113 106 : tevent_req_werror(req, werr);
1114 106 : return;
1115 : }
1116 :
1117 38 : DEBUG(5, ("Error: %s, trying a different forwarder.\n",
1118 : win_errstr(werr)));
1119 38 : subreq = handle_authoritative_send(state, state->ev, state->dns,
1120 38 : state->forwarders->forwarder,
1121 : state->question, &state->answers,
1122 : &state->nsrecs,
1123 : 0); /* cname_depth */
1124 :
1125 38 : if (tevent_req_nomem(subreq, req)) {
1126 0 : return;
1127 : }
1128 :
1129 38 : tevent_req_set_callback(subreq,
1130 : dns_server_process_query_got_auth,
1131 : req);
1132 38 : return;
1133 : }
1134 :
1135 2477 : werr2 = add_zone_authority_record(state->dns,
1136 : state,
1137 2477 : state->question,
1138 : &state->nsrecs);
1139 2477 : if (tevent_req_werror(req, werr2)) {
1140 0 : DBG_WARNING("Failed to add SOA record: %s\n",
1141 : win_errstr(werr2));
1142 0 : return;
1143 : }
1144 :
1145 2477 : state->ancount = talloc_array_length(state->answers);
1146 2477 : state->nscount = talloc_array_length(state->nsrecs);
1147 2477 : state->arcount = talloc_array_length(state->additional);
1148 :
1149 2477 : tevent_req_done(req);
1150 : }
1151 :
1152 2688 : WERROR dns_server_process_query_recv(
1153 : struct tevent_req *req, TALLOC_CTX *mem_ctx,
1154 : struct dns_res_rec **answers, uint16_t *ancount,
1155 : struct dns_res_rec **nsrecs, uint16_t *nscount,
1156 : struct dns_res_rec **additional, uint16_t *arcount)
1157 : {
1158 2688 : struct dns_server_process_query_state *state = tevent_req_data(
1159 : req, struct dns_server_process_query_state);
1160 2688 : WERROR err = WERR_OK;
1161 :
1162 2688 : if (tevent_req_is_werror(req, &err)) {
1163 :
1164 133 : if ((!W_ERROR_EQUAL(err, DNS_ERR(NAME_ERROR))) &&
1165 20 : (!W_ERROR_EQUAL(err, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST))) {
1166 14 : return err;
1167 : }
1168 : }
1169 2674 : *answers = talloc_move(mem_ctx, &state->answers);
1170 2674 : *ancount = state->ancount;
1171 2674 : *nsrecs = talloc_move(mem_ctx, &state->nsrecs);
1172 2674 : *nscount = state->nscount;
1173 2674 : *additional = talloc_move(mem_ctx, &state->additional);
1174 2674 : *arcount = state->arcount;
1175 2674 : return err;
1176 : }
|