From 3e33b9bdbca7b8c896338ae8b96bb7e706442d1b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 14:57:11 +0200 Subject: [PATCH 01/17] s4-dns: Add some NULL checks to create_response_rr --- source4/dns_server/dns_query.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index b3984a4..212c5e4 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -47,9 +47,15 @@ static WERROR create_response_rr(const struct dns_name_question *question, switch (rec->wType) { case DNS_QTYPE_CNAME: ans[ai].rdata.cname_record = talloc_strdup(ans, rec->data.cname); + if (ans[ai].rdata.cname_record == NULL) { + return WERR_NOMEM; + } break; case DNS_QTYPE_A: ans[ai].rdata.ipv4_record = talloc_strdup(ans, rec->data.ipv4); + if (ans[ai].rdata.ipv4_record == NULL) { + return WERR_NOMEM; + } break; case DNS_QTYPE_AAAA: ans[ai].rdata.ipv6_record = rec->data.ipv6; @@ -77,9 +83,15 @@ static WERROR create_response_rr(const struct dns_name_question *question, break; case DNS_QTYPE_TXT: tmp = talloc_asprintf(ans, "\"%s\"", rec->data.txt.str[0]); + if (tmp == NULL) { + return WERR_NOMEM; + } for (i=1; idata.txt.count; i++) { tmp = talloc_asprintf_append(tmp, " \"%s\"", rec->data.txt.str[i]); + if (tmp == NULL) { + return WERR_NOMEM; + } } ans[ai].rdata.txt_record.txt = tmp; break; @@ -89,6 +101,9 @@ static WERROR create_response_rr(const struct dns_name_question *question, } ans[ai].name = talloc_strdup(ans, question->name); + if (ans[ai].name == NULL) { + return WERR_NOMEM; + } ans[ai].rr_type = rec->wType; ans[ai].rr_class = DNS_QCLASS_IN; ans[ai].ttl = rec->dwTtlSeconds; -- 1.7.8 From b0a8d0f75f5ad77d9a4ceeae417e681e572114f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 14:57:49 +0200 Subject: [PATCH 02/17] s4-dns: Use talloc_asprintf_append_buffer in create_response_rr --- source4/dns_server/dns_query.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 212c5e4..11b164a 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -87,8 +87,8 @@ static WERROR create_response_rr(const struct dns_name_question *question, return WERR_NOMEM; } for (i=1; idata.txt.count; i++) { - tmp = talloc_asprintf_append(tmp, " \"%s\"", - rec->data.txt.str[i]); + tmp = talloc_asprintf_append_buffer( + tmp, " \"%s\"", rec->data.txt.str[i]); if (tmp == NULL) { return WERR_NOMEM; } -- 1.7.8 From fa816c953debeab9a8c81eaee42b020f3bae1695 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 15:59:32 +0200 Subject: [PATCH 03/17] s4-dns: Fix an unlikely potential memleak If state was alloc'ed to NULL, in_packet to != NULL and out_packet to NULL, we leak in_packet. --- source4/dns_server/dns_server.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index f9db095..28c57c0 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -117,8 +117,10 @@ static NTSTATUS dns_process(struct dns_server *dns, /* TODO: We don't really need an out_packet. */ out_packet = talloc_zero(state, struct dns_name_packet); - if (in_packet == NULL) return NT_STATUS_NO_MEMORY; - if (out_packet == NULL) return NT_STATUS_NO_MEMORY; + if ((state == NULL) || (in_packet == NULL) || (out_packet == NULL)) { + TALLOC_FREE(state); + return NT_STATUS_NO_MEMORY; + } dump_data(8, in->data, in->length); -- 1.7.8 From ce4ec6c2e1f106878278aa524fca94db5484efb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 16:15:41 +0200 Subject: [PATCH 04/17] s4-dns: Remove some break; statements We fall through implicitly, and that pattern is used elsewhere in Samba as well. --- source4/dns_server/dns_update.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-) diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index 3473a70..16619ab 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -397,21 +397,13 @@ static WERROR handle_one_update(struct dns_server *dns, switch (update->rr_type) { case DNS_QTYPE_A: - break; case DNS_QTYPE_NS: - break; case DNS_QTYPE_CNAME: - break; case DNS_QTYPE_SOA: - break; case DNS_QTYPE_PTR: - break; case DNS_QTYPE_MX: - break; case DNS_QTYPE_AAAA: - break; case DNS_QTYPE_SRV: - break; case DNS_QTYPE_TXT: break; default: -- 1.7.8 From a13c3067eb59f2757ea38ce472df5811ca106479 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2012 08:45:07 +0200 Subject: [PATCH 05/17] librpc: Fix some typos --- librpc/ndr/ndr_dns.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c index 27d8493..0b9e3b0 100644 --- a/librpc/ndr/ndr_dns.c +++ b/librpc/ndr/ndr_dns.c @@ -85,7 +85,7 @@ static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, /* its a reserved length field */ return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD DNS NAME component, " \ - "reserved lenght field: 0x%02x", + "reserved length field: 0x%02x", (len &0xC)); } if (*offset + len + 1 > ndr->data_size) { @@ -256,13 +256,13 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr, return ndr_push_error(ndr, NDR_ERR_LENGTH, "Invalid...Unexpected " \ - "blob lenght is too " \ + "blob length is too " \ "large"); } } if (r->unexpected.length > UINT16_MAX) { return ndr_push_error(ndr, NDR_ERR_LENGTH, - "Unexpected blob lenght "\ + "Unexpected blob length "\ "is too large"); } -- 1.7.8 From e654cdaf9f28570416deb7ca00a530d2ae03b351 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2012 08:53:44 +0200 Subject: [PATCH 06/17] s4-dns: Fix some typos --- source4/dns_server/dns_query.c | 2 +- source4/dns_server/dns_update.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 11b164a..b57a26c 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -259,7 +259,7 @@ WERROR dns_server_process_query(struct dns_server *dns, } else { if (state->flags & DNS_FLAG_RECURSION_DESIRED && state->flags & DNS_FLAG_RECURSION_AVAIL) { - DEBUG(2, ("Not authorative for '%s', forwarding\n", + DEBUG(2, ("Not authoritative for '%s', forwarding\n", in->questions[0].name)); werror = ask_forwarder(dns, mem_ctx, &in->questions[0], &ans, &num_answers, diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index 16619ab..a09818d 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -715,7 +715,7 @@ WERROR dns_server_process_update(struct dns_server *dns, } if (z == NULL) { - DEBUG(0, ("We're not authorative for this zone\n")); + DEBUG(0, ("We're not authoritative for this zone\n")); return DNS_ERR(NOTAUTH); } -- 1.7.8 From 448e97e013e14fbbd8bdc5b5f4e81b709e53e69a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2012 09:45:44 +0200 Subject: [PATCH 07/17] s4-dns: Add debug output for unmappable WERROR to DNS errcode --- source4/dns_server/dns_utils.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c index b4f308c..7d95bdd 100644 --- a/source4/dns_server/dns_utils.c +++ b/source4/dns_server/dns_utils.c @@ -55,7 +55,7 @@ uint8_t werr_to_dns_err(WERROR werr) } else if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) { return DNS_RCODE_NOTZONE; } - DEBUG(5, ("No mapping exists for %%s\n")); + DEBUG(5, ("No mapping exists for %s\n", win_errstr(werr))); return DNS_RCODE_SERVFAIL; } -- 1.7.8 From 973a2a2760743d55edc0ef8fd7a6f33f0f08977e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2012 15:20:21 +0200 Subject: [PATCH 08/17] s4-dns: Create a proper talloc hierarchy in create_response_rr Pair-Programmed-With: Michael Adam --- source4/dns_server/dns_query.c | 18 +++++++++++++++--- 1 files changed, 15 insertions(+), 3 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index b57a26c..3564140 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -67,11 +67,23 @@ static WERROR create_response_rr(const struct dns_name_question *question, ans[ai].rdata.srv_record.priority = rec->data.srv.wPriority; ans[ai].rdata.srv_record.weight = rec->data.srv.wWeight; ans[ai].rdata.srv_record.port = rec->data.srv.wPort; - ans[ai].rdata.srv_record.target = rec->data.srv.nameTarget; + ans[ai].rdata.srv_record.target = talloc_strdup( + ans, rec->data.srv.nameTarget); + if (ans[ai].rdata.srv_record.target == NULL) { + return WERR_NOMEM; + } break; case DNS_QTYPE_SOA: - ans[ai].rdata.soa_record.mname = rec->data.soa.mname; - ans[ai].rdata.soa_record.rname = rec->data.soa.rname; + ans[ai].rdata.soa_record.mname = talloc_strdup( + ans, rec->data.soa.mname); + if (ans[ai].rdata.soa_record.mname == NULL) { + return WERR_NOMEM; + } + ans[ai].rdata.soa_record.rname = talloc_strdup( + ans, rec->data.soa.rname); + if (ans[ai].rdata.soa_record.rname == NULL) { + return WERR_NOMEM; + } ans[ai].rdata.soa_record.serial = rec->data.soa.serial; ans[ai].rdata.soa_record.refresh = rec->data.soa.refresh; ans[ai].rdata.soa_record.retry = rec->data.soa.retry; -- 1.7.8 From 62f20b9b5f4ebff6f983894cd9e3006eb3c1163b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 13:49:26 +0200 Subject: [PATCH 09/17] lib: add tevent_req_poll_werror --- lib/util/tevent_werror.c | 13 +++++++++++++ lib/util/tevent_werror.h | 3 +++ 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/lib/util/tevent_werror.c b/lib/util/tevent_werror.c index d8956b3..47bd809 100644 --- a/lib/util/tevent_werror.c +++ b/lib/util/tevent_werror.c @@ -19,6 +19,7 @@ #include "../replace/replace.h" #include "tevent_werror.h" +#include "libcli/util/error.h" bool _tevent_req_werror(struct tevent_req *req, WERROR werror, @@ -79,3 +80,15 @@ void tevent_req_simple_finish_werror(struct tevent_req *subreq, } tevent_req_done(req); } + +bool tevent_req_poll_werror(struct tevent_req *req, + struct tevent_context *ev, + WERROR *err) +{ + bool ret = tevent_req_poll(req, ev); + if (!ret) { + NTSTATUS status = map_nt_error_from_unix_common(errno); + *err = ntstatus_to_werror(status); + } + return ret; +} diff --git a/lib/util/tevent_werror.h b/lib/util/tevent_werror.h index 0e24382..1e08c3d 100644 --- a/lib/util/tevent_werror.h +++ b/lib/util/tevent_werror.h @@ -40,4 +40,7 @@ WERROR tevent_req_simple_recv_werror(struct tevent_req *req); void tevent_req_simple_finish_werror(struct tevent_req *subreq, WERROR subreq_error); +bool tevent_req_poll_werror(struct tevent_req *req, + struct tevent_context *ev, + WERROR *err); #endif -- 1.7.8 From c287067b39fd6d24934890608aeadca16c39d164 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 13:49:41 +0200 Subject: [PATCH 10/17] s4-dns: Make ask_forwarder async --- source4/dns_server/dns_query.c | 154 +++++++++++++++++++++++++++++----------- 1 files changed, 111 insertions(+), 43 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 3564140..fe4e131 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -32,6 +32,7 @@ #include "dns_server/dns_server.h" #include "libcli/dns/libdns.h" #include "lib/util/util_net.h" +#include "lib/util/tevent_werror.h" static WERROR create_response_rr(const struct dns_name_question *question, const struct dnsp_DnssrvRpcRecord *rec, @@ -128,66 +129,103 @@ static WERROR create_response_rr(const struct dns_name_question *question, return WERR_OK; } -static WERROR ask_forwarder(struct dns_server *dns, - TALLOC_CTX *mem_ctx, - struct dns_name_question *question, - struct dns_res_rec **answers, uint16_t *ancount, - struct dns_res_rec **nsrecs, uint16_t *nscount, - struct dns_res_rec **additional, uint16_t *arcount) +struct ask_forwarder_state { + struct tevent_context *ev; + uint16_t id; + struct dns_name_packet in_packet; +}; + +static void ask_forwarder_done(struct tevent_req *subreq); + +static struct tevent_req *ask_forwarder_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *forwarder, struct dns_name_question *question) { - struct tevent_context *ev = tevent_context_init(mem_ctx); - struct dns_name_packet *out_packet, *in_packet; - uint16_t id = random(); - DATA_BLOB out, in; + struct tevent_req *req, *subreq; + struct ask_forwarder_state *state; + struct dns_name_packet out_packet = { 0, }; + DATA_BLOB out_blob; enum ndr_err_code ndr_err; - WERROR werr = WERR_OK; - struct tevent_req *req; - const char *forwarder = lpcfg_dns_forwarder(dns->task->lp_ctx); + + req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + generate_random_buffer((uint8_t *)&state->id, sizeof(state->id)); if (!is_ipaddress(forwarder)) { DEBUG(0, ("Invalid 'dns forwarder' setting '%s', needs to be " "an IP address\n", forwarder)); - return DNS_ERR(NAME_ERROR); + tevent_req_werror(req, DNS_ERR(NAME_ERROR)); + return tevent_req_post(req, ev); } - out_packet = talloc_zero(mem_ctx, struct dns_name_packet); - W_ERROR_HAVE_NO_MEMORY(out_packet); - - out_packet->id = id; - out_packet->operation |= DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED; + out_packet.id = state->id; + out_packet.operation |= DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED; + out_packet.qdcount = 1; + out_packet.questions = question; - out_packet->qdcount = 1; - out_packet->questions = question; - - ndr_err = ndr_push_struct_blob(&out, mem_ctx, out_packet, - (ndr_push_flags_fn_t)ndr_push_dns_name_packet); + ndr_err = ndr_push_struct_blob( + &out_blob, state, &out_packet, + (ndr_push_flags_fn_t)ndr_push_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return DNS_ERR(SERVER_FAILURE); + tevent_req_werror(req, DNS_ERR(SERVER_FAILURE)); + return tevent_req_post(req, ev); } - - req = dns_udp_request_send(mem_ctx, ev, forwarder, out.data, out.length); - W_ERROR_HAVE_NO_MEMORY(req); - - if(!tevent_req_poll(req, ev)) { - return DNS_ERR(SERVER_FAILURE); + subreq = dns_udp_request_send(state, ev, forwarder, out_blob.data, + out_blob.length); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, ask_forwarder_done, req); + return req; +} - werr = dns_udp_request_recv(req, mem_ctx, &in.data, &in.length); - W_ERROR_NOT_OK_RETURN(werr); +static void ask_forwarder_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct ask_forwarder_state *state = tevent_req_data( + req, struct ask_forwarder_state); + DATA_BLOB in_blob; + enum ndr_err_code ndr_err; + WERROR ret; - in_packet = talloc_zero(mem_ctx, struct dns_name_packet); - W_ERROR_HAVE_NO_MEMORY(in_packet); + ret = dns_udp_request_recv(subreq, state, + &in_blob.data, &in_blob.length); + TALLOC_FREE(subreq); + if (tevent_req_werror(req, ret)) { + return; + } - ndr_err = ndr_pull_struct_blob(&in, in_packet, in_packet, - (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); + ndr_err = ndr_pull_struct_blob( + &in_blob, state, &state->in_packet, + (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return DNS_ERR(SERVER_FAILURE); + tevent_req_werror(req, DNS_ERR(SERVER_FAILURE)); + return; } + if (state->in_packet.id != state->id) { + tevent_req_werror(req, DNS_ERR(NAME_ERROR)); + return; + } + tevent_req_done(req); +} - if (in_packet->id != id) { - DEBUG(0, ("DNS packet id mismatch: 0x%0x, expected 0x%0x\n", - in_packet->id, id)); - return DNS_ERR(NAME_ERROR); +static WERROR ask_forwarder_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct dns_res_rec **answers, uint16_t *ancount, + struct dns_res_rec **nsrecs, uint16_t *nscount, + struct dns_res_rec **additional, uint16_t *arcount) +{ + struct ask_forwarder_state *state = tevent_req_data( + req, struct ask_forwarder_state); + struct dns_name_packet *in_packet = &state->in_packet; + WERROR err; + + if (tevent_req_is_werror(req, &err)) { + return err; } *ancount = in_packet->ancount; @@ -199,7 +237,37 @@ static WERROR ask_forwarder(struct dns_server *dns, *arcount = in_packet->arcount; *additional = talloc_move(mem_ctx, &in_packet->additional); - return werr; + return WERR_OK; +} + +static WERROR ask_forwarder(struct dns_server *dns, + TALLOC_CTX *mem_ctx, + struct dns_name_question *question, + struct dns_res_rec **answers, uint16_t *ancount, + struct dns_res_rec **nsrecs, uint16_t *nscount, + struct dns_res_rec **additional, uint16_t *arcount) +{ + struct tevent_context *ev; + struct tevent_req *req; + WERROR err = WERR_NOMEM; + + ev = tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = ask_forwarder_send( + ev, ev, lpcfg_dns_forwarder(dns->task->lp_ctx), question); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_werror(req, ev, &err)) { + goto fail; + } + err = ask_forwarder_recv(req, mem_ctx, answers, ancount, + nsrecs, nscount, additional, arcount); +fail: + TALLOC_FREE(ev); + return err; } static WERROR handle_question(struct dns_server *dns, -- 1.7.8 From 9aefe02ac14d0438ce5d0f85065c22e1e1f5b689 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 14:53:47 +0200 Subject: [PATCH 11/17] s4-dns: Make dns_server_process_query async --- source4/dns_server/dns_query.c | 157 ++++++++++++++++++++++++++++++---------- 1 files changed, 120 insertions(+), 37 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index fe4e131..65f770c 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -311,59 +311,142 @@ static WERROR handle_question(struct dns_server *dns, } -WERROR dns_server_process_query(struct dns_server *dns, - struct dns_request_state *state, - TALLOC_CTX *mem_ctx, - struct dns_name_packet *in, - struct dns_res_rec **answers, uint16_t *ancount, - struct dns_res_rec **nsrecs, uint16_t *nscount, - struct dns_res_rec **additional, uint16_t *arcount) +struct dns_server_process_query_state { + struct dns_res_rec *answers; + uint16_t ancount; + struct dns_res_rec *nsrecs; + uint16_t nscount; + struct dns_res_rec *additional; + uint16_t arcount; +}; + +static void dns_server_process_query_got_response(struct tevent_req *subreq); + +static struct tevent_req *dns_server_process_query_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct dns_server *dns, struct dns_request_state *req_state, + const struct dns_name_packet *in) { - uint16_t num_answers=0, num_nsrecs=0, num_additional=0; - struct dns_res_rec *ans=NULL, *ns=NULL, *adds=NULL; - WERROR werror; + struct tevent_req *req, *subreq; + struct dns_server_process_query_state *state; + req = tevent_req_create(mem_ctx, &state, + struct dns_server_process_query_state); + if (req == NULL) { + return NULL; + } if (in->qdcount != 1) { - return DNS_ERR(FORMAT_ERROR); + tevent_req_werror(req, DNS_ERR(FORMAT_ERROR)); + return tevent_req_post(req, ev); } /* Windows returns NOT_IMPLEMENTED on this as well */ if (in->questions[0].question_class == DNS_QCLASS_NONE) { - return DNS_ERR(NOT_IMPLEMENTED); + tevent_req_werror(req, DNS_ERR(NOT_IMPLEMENTED)); + return tevent_req_post(req, ev); } if (dns_authorative_for_zone(dns, in->questions[0].name)) { - state->flags |= DNS_FLAG_AUTHORITATIVE; - werror = handle_question(dns, mem_ctx, &in->questions[0], - &ans, &num_answers); - } else { - if (state->flags & DNS_FLAG_RECURSION_DESIRED && - state->flags & DNS_FLAG_RECURSION_AVAIL) { - DEBUG(2, ("Not authoritative for '%s', forwarding\n", - in->questions[0].name)); - werror = ask_forwarder(dns, mem_ctx, &in->questions[0], - &ans, &num_answers, - &ns, &num_nsrecs, - &adds, &num_additional); - } else { - werror = DNS_ERR(NAME_ERROR); + WERROR err; + + req_state->flags |= DNS_FLAG_AUTHORITATIVE; + err = handle_question(dns, state, &in->questions[0], + &state->answers, &state->ancount); + if (tevent_req_werror(req, err)) { + return tevent_req_post(req, ev); } + tevent_req_done(req); + return tevent_req_post(req, ev); } - W_ERROR_NOT_OK_GOTO(werror, query_failed); - *answers = ans; - *ancount = num_answers; + if ((req_state->flags & DNS_FLAG_RECURSION_DESIRED) && + (req_state->flags & DNS_FLAG_RECURSION_AVAIL)) { + DEBUG(2, ("Not authoritative for '%s', forwarding\n", + in->questions[0].name)); + + subreq = ask_forwarder_send( + state, ev, lpcfg_dns_forwarder(dns->task->lp_ctx), + &in->questions[0]); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + subreq, dns_server_process_query_got_response, req); + return req; + } + + tevent_req_werror(req, DNS_ERR(NAME_ERROR)); + return tevent_req_post(req, ev); +} - /*FIXME: Do something for these */ - *nsrecs = ns; - *nscount = num_nsrecs; +static void dns_server_process_query_got_response(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct dns_server_process_query_state *state = tevent_req_data( + req, struct dns_server_process_query_state); + WERROR err; + + err = ask_forwarder_recv(subreq, state, + &state->answers, &state->ancount, + &state->nsrecs, &state->nscount, + &state->additional, &state->arcount); + TALLOC_FREE(subreq); + if (tevent_req_werror(req, err)) { + return; + } + tevent_req_done(req); +} - *additional = adds; - *arcount = num_additional; +static WERROR dns_server_process_query_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct dns_res_rec **answers, uint16_t *ancount, + struct dns_res_rec **nsrecs, uint16_t *nscount, + struct dns_res_rec **additional, uint16_t *arcount) +{ + struct dns_server_process_query_state *state = tevent_req_data( + req, struct dns_server_process_query_state); + WERROR err; + if (tevent_req_is_werror(req, &err)) { + return err; + } + *answers = talloc_move(mem_ctx, &state->answers); + *ancount = state->ancount; + *nsrecs = talloc_move(mem_ctx, &state->nsrecs); + *nscount = state->nscount; + *additional = talloc_move(mem_ctx, &state->additional); + *arcount = state->arcount; return WERR_OK; +} -query_failed: - /*FIXME: add our SOA record to nsrecs */ - return werror; +WERROR dns_server_process_query(struct dns_server *dns, + struct dns_request_state *state, + TALLOC_CTX *mem_ctx, + struct dns_name_packet *in, + struct dns_res_rec **answers, uint16_t *ancount, + struct dns_res_rec **nsrecs, uint16_t *nscount, + struct dns_res_rec **additional, uint16_t *arcount) +{ + struct tevent_context *ev; + struct tevent_req *req; + WERROR err = WERR_NOMEM; + + ev = tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = dns_server_process_query_send(ev, ev, dns, state, in); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_werror(req, ev, &err)) { + goto fail; + } + err = dns_server_process_query_recv(req, mem_ctx, answers, ancount, + nsrecs, nscount, + additional, arcount); +fail: + TALLOC_FREE(ev); + return err; } -- 1.7.8 From 903d52e3ce07c6ee0651b3161069591e7f118c89 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 16:46:29 +0200 Subject: [PATCH 12/17] s4-dns: Remove unused sync ask_forwarder wrapper --- source4/dns_server/dns_query.c | 30 ------------------------------ 1 files changed, 0 insertions(+), 30 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 65f770c..037dc6a 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -240,36 +240,6 @@ static WERROR ask_forwarder_recv( return WERR_OK; } -static WERROR ask_forwarder(struct dns_server *dns, - TALLOC_CTX *mem_ctx, - struct dns_name_question *question, - struct dns_res_rec **answers, uint16_t *ancount, - struct dns_res_rec **nsrecs, uint16_t *nscount, - struct dns_res_rec **additional, uint16_t *arcount) -{ - struct tevent_context *ev; - struct tevent_req *req; - WERROR err = WERR_NOMEM; - - ev = tevent_context_init(talloc_tos()); - if (ev == NULL) { - goto fail; - } - req = ask_forwarder_send( - ev, ev, lpcfg_dns_forwarder(dns->task->lp_ctx), question); - if (req == NULL) { - goto fail; - } - if (!tevent_req_poll_werror(req, ev, &err)) { - goto fail; - } - err = ask_forwarder_recv(req, mem_ctx, answers, ancount, - nsrecs, nscount, additional, arcount); -fail: - TALLOC_FREE(ev); - return err; -} - static WERROR handle_question(struct dns_server *dns, TALLOC_CTX *mem_ctx, const struct dns_name_question *question, -- 1.7.8 From 3588acb9d8982cad5a1d31b711e41e6e6ac8c2cc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 May 2012 17:02:57 +0200 Subject: [PATCH 13/17] s4-dns: Make dns_process_send asyn --- source4/dns_server/dns_query.c | 4 +- source4/dns_server/dns_server.c | 214 +++++++++++++++++++++++++-------------- source4/dns_server/dns_server.h | 10 ++ 3 files changed, 148 insertions(+), 80 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 037dc6a..69fe271 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -292,7 +292,7 @@ struct dns_server_process_query_state { static void dns_server_process_query_got_response(struct tevent_req *subreq); -static struct tevent_req *dns_server_process_query_send( +struct tevent_req *dns_server_process_query_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct dns_server *dns, struct dns_request_state *req_state, const struct dns_name_packet *in) @@ -368,7 +368,7 @@ static void dns_server_process_query_got_response(struct tevent_req *subreq) tevent_req_done(req); } -static WERROR dns_server_process_query_recv( +WERROR dns_server_process_query_recv( struct tevent_req *req, TALLOC_CTX *mem_ctx, struct dns_res_rec **answers, uint16_t *ancount, struct dns_res_rec **nsrecs, uint16_t *nscount, diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index 28c57c0..1643760 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -42,6 +42,7 @@ #include "dsdb/common/util.h" #include "auth/session.h" #include "lib/util/dlinklist.h" +#include "lib/util/tevent_werror.h" NTSTATUS server_service_dns_init(void); @@ -93,113 +94,168 @@ static void dns_tcp_send(struct stream_connection *conn, uint16_t flags) dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called"); } -static NTSTATUS dns_process(struct dns_server *dns, - TALLOC_CTX *mem_ctx, - DATA_BLOB *in, - DATA_BLOB *out) +struct dns_process_state { + DATA_BLOB *in; + struct dns_name_packet in_packet; + struct dns_request_state state; + uint16_t dns_err; + struct dns_name_packet out_packet; + DATA_BLOB out; +}; + +static void dns_process_done(struct tevent_req *subreq); + +static struct tevent_req *dns_process_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct dns_server *dns, + DATA_BLOB *in) { + struct tevent_req *req, *subreq; + struct dns_process_state *state; enum ndr_err_code ndr_err; WERROR ret; - uint16_t dns_err = DNS_RCODE_OK; - struct dns_request_state *state; - struct dns_name_packet *in_packet; - struct dns_name_packet *out_packet; - struct dns_res_rec *answers = NULL, *nsrecs = NULL, *additional = NULL; - uint16_t num_answers = 0 , num_nsrecs = 0, num_additional = 0; - if (in->length < 12) { - return NT_STATUS_INVALID_PARAMETER; + req = tevent_req_create(mem_ctx, &state, struct dns_process_state); + if (req == NULL) { + return NULL; } + state->in = in; - state = talloc_zero(mem_ctx, struct dns_request_state); - - in_packet = talloc_zero(state, struct dns_name_packet); - /* TODO: We don't really need an out_packet. */ - out_packet = talloc_zero(state, struct dns_name_packet); - - if ((state == NULL) || (in_packet == NULL) || (out_packet == NULL)) { - TALLOC_FREE(state); - return NT_STATUS_NO_MEMORY; + if (in->length < 12) { + tevent_req_werror(req, WERR_INVALID_PARAM); + return tevent_req_post(req, ev); } - dump_data(8, in->data, in->length); - ndr_err = ndr_pull_struct_blob(in, in_packet, in_packet, - (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); + ndr_err = ndr_pull_struct_blob( + in, state, &state->in_packet, + (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - TALLOC_FREE(in_packet); - DEBUG(0, ("Failed to parse packet %d!\n", ndr_err)); - dns_err = DNS_RCODE_FORMERR; - goto drop; + state->dns_err = DNS_RCODE_FORMERR; + tevent_req_done(req); + return tevent_req_post(req, ev); } if (DEBUGLVL(8)) { - NDR_PRINT_DEBUG(dns_name_packet, in_packet); + NDR_PRINT_DEBUG(dns_name_packet, &state->in_packet); } - *out_packet = *in_packet; - state->flags |= in_packet->operation | DNS_FLAG_REPLY; + + state->state.flags = state->in_packet.operation; + state->state.flags |= DNS_FLAG_REPLY; if (lpcfg_dns_recursive_queries(dns->task->lp_ctx)) { - state->flags |= DNS_FLAG_RECURSION_AVAIL; + state->state.flags |= DNS_FLAG_RECURSION_AVAIL; } - switch (in_packet->operation & DNS_OPCODE) { - case DNS_OPCODE_QUERY: - - ret = dns_server_process_query(dns, state, - out_packet, in_packet, - &answers, &num_answers, - &nsrecs, &num_nsrecs, - &additional, &num_additional); + state->out_packet = state->in_packet; - break; + switch (state->in_packet.operation & DNS_OPCODE) { + case DNS_OPCODE_QUERY: + subreq = dns_server_process_query_send( + state, ev, dns, &state->state, &state->in_packet); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, dns_process_done, req); + return req; case DNS_OPCODE_UPDATE: - ret = dns_server_process_update(dns, state, - out_packet, in_packet, - &answers, &num_answers, - &nsrecs, &num_nsrecs, - &additional, &num_additional); + ret = dns_server_process_update( + dns, &state->state, state, &state->in_packet, + &state->out_packet.answers, &state->out_packet.ancount, + &state->out_packet.nsrecs, &state->out_packet.nscount, + &state->out_packet.additional, + &state->out_packet.arcount); break; default: ret = WERR_DNS_ERROR_RCODE_NOT_IMPLEMENTED; - break; } + if (!W_ERROR_IS_OK(ret)) { + state->dns_err = werr_to_dns_err(ret); + } + tevent_req_done(req); + return tevent_req_post(req, ev); +} - if (W_ERROR_IS_OK(ret)) { - out_packet->ancount = num_answers; - out_packet->answers = answers; +static void dns_process_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct dns_process_state *state = tevent_req_data( + req, struct dns_process_state); + WERROR ret; - out_packet->nscount = num_nsrecs; - out_packet->nsrecs = nsrecs; + ret = dns_server_process_query_recv( + subreq, state, + &state->out_packet.answers, &state->out_packet.ancount, + &state->out_packet.nsrecs, &state->out_packet.nscount, + &state->out_packet.additional, &state->out_packet.arcount); + TALLOC_FREE(subreq); - out_packet->arcount = num_additional; - out_packet->additional = additional; - } else { - out_packet->operation |= werr_to_dns_err(ret); + if (!W_ERROR_IS_OK(ret)) { + state->dns_err = werr_to_dns_err(ret); } + tevent_req_done(req); +} - out_packet->operation |= state->flags; +static WERROR dns_process_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + DATA_BLOB *out) +{ + struct dns_process_state *state = tevent_req_data( + req, struct dns_process_state); + enum ndr_err_code ndr_err; + WERROR ret; - if (DEBUGLVL(8)) { - NDR_PRINT_DEBUG(dns_name_packet, out_packet); + if (tevent_req_is_werror(req, &ret)) { + return ret; } - ndr_err = ndr_push_struct_blob(out, out_packet, out_packet, - (ndr_push_flags_fn_t)ndr_push_dns_name_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - TALLOC_FREE(in_packet); - TALLOC_FREE(out_packet); - DEBUG(0, ("Failed to push packet %d!\n", ndr_err)); - dns_err = DNS_RCODE_SERVFAIL; + if (state->dns_err != DNS_RCODE_OK) { goto drop; } + state->out_packet.operation |= state->state.flags; - dump_data(8, out->data, out->length); - return NT_STATUS_OK; + ndr_err = ndr_push_struct_blob( + out, mem_ctx, &state->out_packet, + (ndr_push_flags_fn_t)ndr_push_dns_name_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(1, ("Failed to push packet: %s!\n", + ndr_errstr(ndr_err))); + state->dns_err = DNS_RCODE_SERVFAIL; + goto drop; + } + return WERR_OK; drop: - *out = *in; + *out = data_blob_talloc(mem_ctx, state->in->data, state->in->length); + if (out->data == NULL) { + return WERR_NOMEM; + } out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */ - out->data[3] |= dns_err; - return NT_STATUS_OK; + out->data[3] |= state->dns_err; + return WERR_OK; +} + +static WERROR dns_process(struct dns_server *dns, TALLOC_CTX *mem_ctx, + DATA_BLOB *in, DATA_BLOB *out) +{ + struct tevent_context *ev; + struct tevent_req *req; + WERROR err = WERR_NOMEM; + + ev = tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = dns_process_send(ev, ev, dns, in); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_werror(req, ev, &err)) { + goto fail; + } + err = dns_process_recv(req, mem_ctx, out); +fail: + TALLOC_FREE(ev); + return err; } struct dns_tcp_call { @@ -218,6 +274,7 @@ static void dns_tcp_call_loop(struct tevent_req *subreq) struct dns_tcp_connection); struct dns_tcp_call *call; NTSTATUS status; + WERROR err; call = talloc(dns_conn, struct dns_tcp_call); if (call == NULL) { @@ -254,9 +311,10 @@ static void dns_tcp_call_loop(struct tevent_req *subreq) call->in.length -= 2; /* Call dns */ - status = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("dns_process returned %s\n", nt_errstr(status))); + err = dns_process(dns_conn->dns_socket->dns, call, &call->in, + &call->out); + if (!W_ERROR_IS_OK(err)) { + DEBUG(1, ("dns_process returned %s\n", win_errstr(err))); dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: process function failed"); return; @@ -410,7 +468,7 @@ static void dns_udp_call_loop(struct tevent_req *subreq) uint8_t *buf; ssize_t len; int sys_errno; - NTSTATUS status; + WERROR err; call = talloc(sock, struct dns_udp_call); if (call == NULL) { @@ -434,10 +492,10 @@ static void dns_udp_call_loop(struct tevent_req *subreq) tsocket_address_string(call->src, call))); /* Call dns_process */ - status = dns_process(sock->dns_socket->dns, call, &call->in, &call->out); - if (!NT_STATUS_IS_OK(status)) { + err = dns_process(sock->dns_socket->dns, call, &call->in, &call->out); + if (!W_ERROR_IS_OK(err)) { talloc_free(call); - DEBUG(0, ("dns_process returned %s\n", nt_errstr(status))); + DEBUG(0, ("dns_process returned %s\n", win_errstr(err))); goto done; } diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h index c6f5fb3..853ff07 100644 --- a/source4/dns_server/dns_server.h +++ b/source4/dns_server/dns_server.h @@ -43,6 +43,16 @@ struct dns_request_state { uint16_t flags; }; +struct tevent_req *dns_server_process_query_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct dns_server *dns, struct dns_request_state *req_state, + const struct dns_name_packet *in); +WERROR dns_server_process_query_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct dns_res_rec **answers, uint16_t *ancount, + struct dns_res_rec **nsrecs, uint16_t *nscount, + struct dns_res_rec **additional, uint16_t *arcount); + WERROR dns_server_process_query(struct dns_server *dns, struct dns_request_state *state, TALLOC_CTX *mem_ctx, -- 1.7.8 From 2281eb735458b4dc6ea82c91daedcc7e273f8248 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2012 18:23:50 +0200 Subject: [PATCH 14/17] s4-dns: Remove sync dns_server_process_query --- source4/dns_server/dns_query.c | 31 ------------------------------- source4/dns_server/dns_server.h | 8 -------- 2 files changed, 0 insertions(+), 39 deletions(-) diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c index 69fe271..419f67e 100644 --- a/source4/dns_server/dns_query.c +++ b/source4/dns_server/dns_query.c @@ -389,34 +389,3 @@ WERROR dns_server_process_query_recv( *arcount = state->arcount; return WERR_OK; } - -WERROR dns_server_process_query(struct dns_server *dns, - struct dns_request_state *state, - TALLOC_CTX *mem_ctx, - struct dns_name_packet *in, - struct dns_res_rec **answers, uint16_t *ancount, - struct dns_res_rec **nsrecs, uint16_t *nscount, - struct dns_res_rec **additional, uint16_t *arcount) -{ - struct tevent_context *ev; - struct tevent_req *req; - WERROR err = WERR_NOMEM; - - ev = tevent_context_init(talloc_tos()); - if (ev == NULL) { - goto fail; - } - req = dns_server_process_query_send(ev, ev, dns, state, in); - if (req == NULL) { - goto fail; - } - if (!tevent_req_poll_werror(req, ev, &err)) { - goto fail; - } - err = dns_server_process_query_recv(req, mem_ctx, answers, ancount, - nsrecs, nscount, - additional, arcount); -fail: - TALLOC_FREE(ev); - return err; -} diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h index 853ff07..f871544 100644 --- a/source4/dns_server/dns_server.h +++ b/source4/dns_server/dns_server.h @@ -53,14 +53,6 @@ WERROR dns_server_process_query_recv( struct dns_res_rec **nsrecs, uint16_t *nscount, struct dns_res_rec **additional, uint16_t *arcount); -WERROR dns_server_process_query(struct dns_server *dns, - struct dns_request_state *state, - TALLOC_CTX *mem_ctx, - struct dns_name_packet *in, - struct dns_res_rec **answers, uint16_t *ancount, - struct dns_res_rec **nsrecs, uint16_t *nscount, - struct dns_res_rec **additional, uint16_t *arcount); - WERROR dns_server_process_update(struct dns_server *dns, struct dns_request_state *state, TALLOC_CTX *mem_ctx, -- 1.7.8 From fc88123475f3474378a983e15be8283a0472e393 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2012 18:42:54 +0200 Subject: [PATCH 15/17] s4-dns: Make the UDP dns server async --- source4/dns_server/dns_server.c | 56 ++++++++++++++++++++++++++------------ 1 files changed, 38 insertions(+), 18 deletions(-) diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index 1643760..e4cff0b 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -453,28 +453,31 @@ static const struct stream_server_ops dns_tcp_stream_ops = { }; struct dns_udp_call { + struct dns_udp_socket *sock; struct tsocket_address *src; DATA_BLOB in; DATA_BLOB out; }; +static void dns_udp_call_process_done(struct tevent_req *subreq); static void dns_udp_call_sendto_done(struct tevent_req *subreq); static void dns_udp_call_loop(struct tevent_req *subreq) { struct dns_udp_socket *sock = tevent_req_callback_data(subreq, struct dns_udp_socket); + struct dns_server *dns = sock->dns_socket->dns; struct dns_udp_call *call; uint8_t *buf; ssize_t len; int sys_errno; - WERROR err; call = talloc(sock, struct dns_udp_call); if (call == NULL) { talloc_free(call); goto done; } + call->sock = sock; len = tdgram_recvfrom_recv(subreq, &sys_errno, call, &buf, &call->src); @@ -491,26 +494,13 @@ static void dns_udp_call_loop(struct tevent_req *subreq) (long)call->in.length, tsocket_address_string(call->src, call))); - /* Call dns_process */ - err = dns_process(sock->dns_socket->dns, call, &call->in, &call->out); - if (!W_ERROR_IS_OK(err)) { - talloc_free(call); - DEBUG(0, ("dns_process returned %s\n", win_errstr(err))); - goto done; - } - - subreq = tdgram_sendto_queue_send(call, - sock->dns_socket->dns->task->event_ctx, - sock->dgram, - sock->send_queue, - call->out.data, - call->out.length, - call->src); + subreq = dns_process_send(call, dns->task->event_ctx, dns, + &call->in); if (subreq == NULL) { - talloc_free(call); + TALLOC_FREE(call); goto done; } - tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call); + tevent_req_set_callback(subreq, dns_udp_call_process_done, call); done: subreq = tdgram_recvfrom_send(sock, @@ -525,6 +515,36 @@ done: tevent_req_set_callback(subreq, dns_udp_call_loop, sock); } +static void dns_udp_call_process_done(struct tevent_req *subreq) +{ + struct dns_udp_call *call = tevent_req_callback_data( + subreq, struct dns_udp_call); + struct dns_udp_socket *sock = call->sock; + struct dns_server *dns = sock->dns_socket->dns; + WERROR err; + + err = dns_process_recv(subreq, call, &call->out); + TALLOC_FREE(subreq); + if (!W_ERROR_IS_OK(err)) { + DEBUG(1, ("dns_process returned %s\n", win_errstr(err))); + TALLOC_FREE(call); + return; + } + + subreq = tdgram_sendto_queue_send(call, + dns->task->event_ctx, + sock->dgram, + sock->send_queue, + call->out.data, + call->out.length, + call->src); + if (subreq == NULL) { + talloc_free(call); + return; + } + tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call); + +} static void dns_udp_call_sendto_done(struct tevent_req *subreq) { struct dns_udp_call *call = tevent_req_callback_data(subreq, -- 1.7.8 From a0f835b4ace783721c57bd73fe1144fa1337657d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 May 2012 18:42:54 +0200 Subject: [PATCH 16/17] s4-dns: Make the TCP dns server async --- source4/dns_server/dns_server.c | 60 +++++++++++++++++++++++++------------- 1 files changed, 39 insertions(+), 21 deletions(-) diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index e4cff0b..caf347d 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -266,15 +266,16 @@ struct dns_tcp_call { struct iovec out_iov[2]; }; +static void dns_tcp_call_process_done(struct tevent_req *subreq); static void dns_tcp_call_writev_done(struct tevent_req *subreq); static void dns_tcp_call_loop(struct tevent_req *subreq) { struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq, struct dns_tcp_connection); + struct dns_server *dns = dns_conn->dns_socket->dns; struct dns_tcp_call *call; NTSTATUS status; - WERROR err; call = talloc(dns_conn, struct dns_tcp_call); if (call == NULL) { @@ -310,9 +311,43 @@ static void dns_tcp_call_loop(struct tevent_req *subreq) call->in.data += 2; call->in.length -= 2; - /* Call dns */ - err = dns_process(dns_conn->dns_socket->dns, call, &call->in, - &call->out); + subreq = dns_process_send(call, dns->task->event_ctx, dns, + &call->in); + if (subreq == NULL) { + dns_tcp_terminate_connection( + dns_conn, "dns_tcp_call_loop: dns_process_send " + "failed\n"); + return; + } + tevent_req_set_callback(subreq, dns_tcp_call_process_done, call); + + /* + * The dns tcp pdu's has the length as 2 byte (initial_read_size), + * packet_full_request_u16 provides the pdu length then. + */ + subreq = tstream_read_pdu_blob_send(dns_conn, + dns_conn->conn->event.ctx, + dns_conn->tstream, + 2, /* initial_read_size */ + packet_full_request_u16, + dns_conn); + if (subreq == NULL) { + dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: " + "no memory for tstream_read_pdu_blob_send"); + return; + } + tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn); +} + +static void dns_tcp_call_process_done(struct tevent_req *subreq) +{ + struct dns_tcp_call *call = tevent_req_callback_data(subreq, + struct dns_tcp_call); + struct dns_tcp_connection *dns_conn = call->dns_conn; + WERROR err; + + err = dns_process_recv(subreq, call, &call->out); + TALLOC_FREE(subreq); if (!W_ERROR_IS_OK(err)) { DEBUG(1, ("dns_process returned %s\n", win_errstr(err))); dns_tcp_terminate_connection(dns_conn, @@ -339,23 +374,6 @@ static void dns_tcp_call_loop(struct tevent_req *subreq) return; } tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call); - - /* - * The dns tcp pdu's has the length as 2 byte (initial_read_size), - * packet_full_request_u16 provides the pdu length then. - */ - subreq = tstream_read_pdu_blob_send(dns_conn, - dns_conn->conn->event.ctx, - dns_conn->tstream, - 2, /* initial_read_size */ - packet_full_request_u16, - dns_conn); - if (subreq == NULL) { - dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: " - "no memory for tstream_read_pdu_blob_send"); - return; - } - tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn); } static void dns_tcp_call_writev_done(struct tevent_req *subreq) -- 1.7.8 From d33feedef2b6df064e04c4fac08408614548a6c4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 29 May 2012 10:03:13 +0200 Subject: [PATCH 17/17] s4-dns: Remove sync dns_process --- source4/dns_server/dns_server.c | 24 ------------------------ 1 files changed, 0 insertions(+), 24 deletions(-) diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index caf347d..34e4fe3 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -234,30 +234,6 @@ drop: return WERR_OK; } -static WERROR dns_process(struct dns_server *dns, TALLOC_CTX *mem_ctx, - DATA_BLOB *in, DATA_BLOB *out) -{ - struct tevent_context *ev; - struct tevent_req *req; - WERROR err = WERR_NOMEM; - - ev = tevent_context_init(talloc_tos()); - if (ev == NULL) { - goto fail; - } - req = dns_process_send(ev, ev, dns, in); - if (req == NULL) { - goto fail; - } - if (!tevent_req_poll_werror(req, ev, &err)) { - goto fail; - } - err = dns_process_recv(req, mem_ctx, out); -fail: - TALLOC_FREE(ev); - return err; -} - struct dns_tcp_call { struct dns_tcp_connection *dns_conn; DATA_BLOB in; -- 1.7.8