The branch, master has been updated
       via  5a72a2e dns_server: Remove unused handle_question
       via  6adec93 dns_server: Add handle_authoritative_send()
       via  3b7f99e dns_server: Add add_dns_res_rec()
       via  b6aaf77 dns_server: Convert "ask_forwarder" params
       via  4b54e14 dns_server: Simplify array length handling
       via  3f2cbb6 dns_server: Simplify talloc handling
       via  9de59c7 dns_server: Consolidate talloc_realloc
      from  4807577 Fix bug 10881 Wrong keytab permissions when joining 
additional DC with BIND backend

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 5a72a2ed0d28004d51039313e84047554c0a8f63
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Aug 11 07:40:50 2015 +0200

    dns_server: Remove unused handle_question
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>
    
    Autobuild-User(master): Kai Blin <k...@samba.org>
    Autobuild-Date(master): Tue Dec 15 17:50:32 CET 2015 on sn-devel-104

commit 6adec9339dee488e41c7552451eca45ebae4b917
Author: Volker Lendecke <v...@samba.org>
Date:   Tue Aug 11 07:39:31 2015 +0200

    dns_server: Add handle_authoritative_send()
    
    An async version of handle_question
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=9409
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

commit 3b7f99e6f4996cfd97220b3a6d5cceeab6ab5b79
Author: Volker Lendecke <v...@samba.org>
Date:   Sat Aug 8 14:36:43 2015 +0200

    dns_server: Add add_dns_res_rec()
    
    Same as add_response_rr(), but it copies over a dns_res_rec
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

commit b6aaf77897082c6ac447e9514260b435ac3ad854
Author: Volker Lendecke <v...@samba.org>
Date:   Sat Aug 8 07:20:26 2015 +0200

    dns_server: Convert "ask_forwarder" params
    
    Usually we have mem_ctx and ev first when doing a _send function
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

commit 4b54e14b7cf456e327b176b365e8471e0899210b
Author: Volker Lendecke <v...@samba.org>
Date:   Sat Aug 8 06:54:11 2015 +0200

    dns_server: Simplify array length handling
    
    talloc objects carry an implicit length
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

commit 3f2cbb616f8b0becf8a3479e72dda11433126e65
Author: Volker Lendecke <v...@samba.org>
Date:   Sat Aug 8 06:49:16 2015 +0200

    dns_server: Simplify talloc handling
    
    By making sure that the answers are always allocated, we don't have
    to pass an explicit mem_ctx anymore
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

commit 9de59c7e3f01c578831a8e352ff8e9ee2312c77f
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Aug 7 08:27:19 2015 +0200

    dns_server: Consolidate talloc_realloc
    
    This puts the talloc_realloc into add_response_rr instead of before
    create_response_rr. It is a bit less efficient, but as we do not expect
    hundreds of answers, I think this code is a bit easier to understand.
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Kai Blin <k...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source4/dns_server/dns_query.c | 531 +++++++++++++++++++++++++++++++++--------
 1 file changed, 425 insertions(+), 106 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 956898e..63c219a 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -40,15 +40,27 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DNS
 
-static WERROR create_response_rr(const char *name,
-                                const struct dnsp_DnssrvRpcRecord *rec,
-                                struct dns_res_rec **answers, uint16_t 
*ancount)
+static WERROR add_response_rr(const char *name,
+                             const struct dnsp_DnssrvRpcRecord *rec,
+                             struct dns_res_rec **answers)
 {
        struct dns_res_rec *ans = *answers;
-       uint16_t ai = *ancount;
+       uint16_t ai = talloc_array_length(ans);
        char *tmp;
        uint32_t i;
 
+       if (ai == UINT16_MAX) {
+               return WERR_BUFFER_OVERFLOW;
+       }
+
+       /*
+        * "ans" is always non-NULL and thus its own talloc context
+        */
+       ans = talloc_realloc(ans, ans, struct dns_res_rec, ai+1);
+       if (ans == NULL) {
+               return WERR_NOMEM;
+       }
+
        ZERO_STRUCT(ans[ai]);
 
        switch (rec->wType) {
@@ -122,10 +134,132 @@ static WERROR create_response_rr(const char *name,
        ans[ai].rr_class = DNS_QCLASS_IN;
        ans[ai].ttl = rec->dwTtlSeconds;
        ans[ai].length = UINT16_MAX;
-       ai++;
 
        *answers = ans;
-       *ancount = ai;
+
+       return WERR_OK;
+}
+
+static WERROR add_dns_res_rec(struct dns_res_rec **pdst,
+                             const struct dns_res_rec *src)
+{
+       struct dns_res_rec *dst = *pdst;
+       uint16_t di = talloc_array_length(dst);
+
+       if (di == UINT16_MAX) {
+               return WERR_BUFFER_OVERFLOW;
+       }
+
+       dst = talloc_realloc(dst, dst, struct dns_res_rec, di+1);
+       if (dst == NULL) {
+               return WERR_NOMEM;
+       }
+
+       ZERO_STRUCT(dst[di]);
+
+       dst[di] = (struct dns_res_rec) {
+               .name = talloc_strdup(dst, src->name),
+               .rr_type = src->rr_type,
+               .rr_class = src->rr_class,
+               .ttl = src->ttl,
+               .length = src->length
+       };
+
+       if (dst[di].name == NULL) {
+               return WERR_NOMEM;
+       }
+
+       switch (src->rr_type) {
+       case DNS_QTYPE_CNAME:
+               dst[di].rdata.cname_record = talloc_strdup(
+                       dst, src->rdata.cname_record);
+               if (dst[di].rdata.cname_record == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_A:
+               dst[di].rdata.ipv4_record = talloc_strdup(
+                       dst, src->rdata.ipv4_record);
+               if (dst[di].rdata.ipv4_record == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_AAAA:
+               dst[di].rdata.ipv6_record = talloc_strdup(
+                       dst, src->rdata.ipv6_record);
+               if (dst[di].rdata.ipv6_record == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_TYPE_NS:
+               dst[di].rdata.ns_record = talloc_strdup(
+                       dst, src->rdata.ns_record);
+               if (dst[di].rdata.ns_record == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_SRV:
+               dst[di].rdata.srv_record = (struct dns_srv_record) {
+                       .priority = src->rdata.srv_record.priority,
+                       .weight   = src->rdata.srv_record.weight,
+                       .port     = src->rdata.srv_record.port,
+                       .target   = talloc_strdup(
+                               dst, src->rdata.srv_record.target)
+               };
+               if (dst[di].rdata.srv_record.target == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_SOA:
+               dst[di].rdata.soa_record = (struct dns_soa_record) {
+                       .mname   = talloc_strdup(
+                               dst, src->rdata.soa_record.mname),
+                       .rname   = talloc_strdup(
+                               dst, src->rdata.soa_record.rname),
+                       .serial  = src->rdata.soa_record.serial,
+                       .refresh = src->rdata.soa_record.refresh,
+                       .retry   = src->rdata.soa_record.retry,
+                       .expire  = src->rdata.soa_record.expire,
+                       .minimum = src->rdata.soa_record.minimum
+               };
+
+               if ((dst[di].rdata.soa_record.mname == NULL) ||
+                   (dst[di].rdata.soa_record.rname == NULL)) {
+                       return WERR_NOMEM;
+               }
+
+               break;
+       case DNS_QTYPE_PTR:
+               dst[di].rdata.ptr_record = talloc_strdup(
+                       dst, src->rdata.ptr_record);
+               if (dst[di].rdata.ptr_record == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_MX:
+               dst[di].rdata.mx_record = (struct dns_mx_record) {
+                       .preference = src->rdata.mx_record.preference,
+                       .exchange   = talloc_strdup(
+                               src, src->rdata.mx_record.exchange)
+               };
+
+               if (dst[di].rdata.mx_record.exchange == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       case DNS_QTYPE_TXT:
+               dst[di].rdata.txt_record.txt = talloc_strdup(
+                       dst, src->rdata.txt_record.txt);
+               if (dst[di].rdata.txt_record.txt == NULL) {
+                       return WERR_NOMEM;
+               }
+               break;
+       default:
+               DBG_WARNING("Got unhandled type %u query.\n", src->rr_type);
+               return DNS_ERR(NOT_IMPLEMENTED);
+       }
+
+       *pdst = dst;
 
        return WERR_OK;
 }
@@ -139,8 +273,8 @@ struct ask_forwarder_state {
 static void ask_forwarder_done(struct tevent_req *subreq);
 
 static struct tevent_req *ask_forwarder_send(
-       struct dns_server *dns,
        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct dns_server *dns,
        const char *forwarder, struct dns_name_question *question)
 {
        struct tevent_req *req, *subreq;
@@ -258,12 +392,12 @@ static WERROR ask_forwarder_recv(
 static WERROR add_zone_authority_record(struct dns_server *dns,
                                        TALLOC_CTX *mem_ctx,
                                        const struct dns_name_question 
*question,
-                                       struct dns_res_rec **nsrecs, uint16_t 
*nscount)
+                                       struct dns_res_rec **nsrecs)
 {
        const char *zone = NULL;
        struct dnsp_DnssrvRpcRecord *recs;
        struct dns_res_rec *ns = *nsrecs;
-       uint16_t rec_count, ni = *nscount;
+       uint16_t rec_count;
        struct ldb_dn *dn = NULL;
        unsigned int ri;
        WERROR werror;
@@ -281,127 +415,283 @@ static WERROR add_zone_authority_record(struct 
dns_server *dns,
                return werror;
        }
 
-       ns = talloc_realloc(mem_ctx, ns, struct dns_res_rec, rec_count + ni);
-       if (ns == NULL) {
-               return WERR_NOMEM;
-       }
        for (ri = 0; ri < rec_count; ri++) {
                if (recs[ri].wType == DNS_TYPE_SOA) {
-                       werror = create_response_rr(zone, &recs[ri], &ns, &ni);
+                       werror = add_response_rr(zone, &recs[ri], &ns);
                        if (!W_ERROR_IS_OK(werror)) {
                                return werror;
                        }
                }
        }
 
-       *nscount = ni;
        *nsrecs = ns;
 
        return WERR_OK;
 }
 
+static struct tevent_req *handle_authoritative_send(
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct dns_server *dns, const char *forwarder,
+       struct dns_name_question *question,
+       struct dns_res_rec **answers, struct dns_res_rec **nsrecs);
+static WERROR handle_authoritative_recv(struct tevent_req *req);
+
+struct handle_dnsrpcrec_state {
+       struct dns_res_rec **answers;
+       struct dns_res_rec **nsrecs;
+};
+
+static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq);
+static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq);
 
-static WERROR handle_question(struct dns_server *dns,
-                             TALLOC_CTX *mem_ctx,
-                             const struct dns_name_question *question,
-                             struct dns_res_rec **answers, uint16_t *ancount,
-                             struct dns_res_rec **nsrecs, uint16_t *nscount)
+static struct tevent_req *handle_dnsrpcrec_send(
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct dns_server *dns, const char *forwarder,
+       const struct dns_name_question *question,
+       struct dnsp_DnssrvRpcRecord *rec,
+       struct dns_res_rec **answers, struct dns_res_rec **nsrecs)
 {
-       struct dns_res_rec *ans = *answers;
-       struct dns_res_rec *ns = *nsrecs;
-       WERROR werror, werror_return;
-       unsigned int ri;
-       struct dnsp_DnssrvRpcRecord *recs;
-       uint16_t rec_count, ai = *ancount, ni = *nscount;
-       struct ldb_dn *dn = NULL;
+       struct tevent_req *req, *subreq;
+       struct handle_dnsrpcrec_state *state;
+       struct dns_name_question *new_q;
+       bool resolve_cname;
+       WERROR werr;
 
-       werror = dns_name2dn(dns, mem_ctx, question->name, &dn);
-       if (!W_ERROR_IS_OK(werror)) {
-               return werror;
+       req = tevent_req_create(mem_ctx, &state,
+                               struct handle_dnsrpcrec_state);
+       if (req == NULL) {
+               return NULL;
        }
+       state->answers = answers;
+       state->nsrecs = nsrecs;
 
-       werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count);
-       if (!W_ERROR_IS_OK(werror)) {
-               werror_return = werror;
-               goto done;
+       resolve_cname = ((rec->wType == DNS_TYPE_CNAME) &&
+                        ((question->question_type == DNS_QTYPE_A) ||
+                         (question->question_type == DNS_QTYPE_AAAA)));
+
+       if (!resolve_cname) {
+               if ((question->question_type != DNS_QTYPE_ALL) &&
+                   (rec->wType !=
+                    (enum dns_record_type) question->question_type)) {
+                       tevent_req_done(req);
+                       return tevent_req_post(req, ev);
+               }
+
+               werr = add_response_rr(question->name, rec, state->answers);
+               if (tevent_req_werror(req, werr)) {
+                       return tevent_req_post(req, ev);
+               }
+
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
        }
 
-       ans = talloc_realloc(mem_ctx, ans, struct dns_res_rec, rec_count + ai);
-       if (ans == NULL) {
-               return WERR_NOMEM;
+       werr = add_response_rr(question->name, rec, state->answers);
+       if (tevent_req_werror(req, werr)) {
+               return tevent_req_post(req, ev);
        }
 
-       /* Set up for an NXDOMAIN reply if no match is found */
-       werror_return = DNS_ERR(NAME_ERROR);
+       new_q = talloc(state, struct dns_name_question);
+       if (tevent_req_nomem(new_q, req)) {
+               return tevent_req_post(req, ev);
+       }
 
-       for (ri = 0; ri < rec_count; ri++) {
-               if ((recs[ri].wType == DNS_TYPE_CNAME) &&
-                   ((question->question_type == DNS_QTYPE_A) ||
-                    (question->question_type == DNS_QTYPE_AAAA))) {
-                       struct dns_name_question *new_q =
-                               talloc(mem_ctx, struct dns_name_question);
+       *new_q = (struct dns_name_question) {
+               .question_type = question->question_type,
+               .question_class = question->question_class,
+               .name = rec->data.cname
+       };
 
-                       if (new_q == NULL) {
-                               return WERR_NOMEM;
-                       }
+       if (dns_authorative_for_zone(dns, new_q->name)) {
+               subreq = handle_authoritative_send(
+                       state, ev, dns, forwarder, new_q,
+                       state->answers, state->nsrecs);
+               if (tevent_req_nomem(subreq, req)) {
+                       return tevent_req_post(req, ev);
+               }
+               tevent_req_set_callback(subreq, handle_dnsrpcrec_gotauth, req);
+               return req;
+       }
 
-                       /* We reply with one more record, so grow the array */
-                       ans = talloc_realloc(mem_ctx, ans, struct dns_res_rec,
-                                            rec_count + 1);
-                       if (ans == NULL) {
-                               TALLOC_FREE(new_q);
-                               return WERR_NOMEM;
-                       }
+       subreq = ask_forwarder_send(state, ev, dns, forwarder, new_q);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, handle_dnsrpcrec_gotforwarded, req);
 
-                       /* First put in the CNAME record */
-                       werror = create_response_rr(question->name, &recs[ri], 
&ans, &ai);
-                       if (!W_ERROR_IS_OK(werror)) {
-                               TALLOC_FREE(new_q);
-                               return werror;
-                       }
+       return req;
+}
 
-                       /* And then look up the name it points at.. */
+static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       WERROR werr;
 
-                       /* First build up the new question */
-                       new_q->question_type = question->question_type;
-                       new_q->question_class = question->question_class;
-                       new_q->name = talloc_strdup(new_q, recs[ri].data.cname);
-                       if (new_q->name == NULL) {
-                               TALLOC_FREE(new_q);
-                               return WERR_NOMEM;
-                       }
-                       /* and then call the lookup again */
-                       werror = handle_question(dns, mem_ctx, new_q, &ans, 
&ai, &ns, &ni);
-                       if (!W_ERROR_IS_OK(werror)) {
-                               goto done;
-                       }
-                       werror_return = WERR_OK;
+       werr = handle_authoritative_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (tevent_req_werror(req, werr)) {
+               return;
+       }
+       tevent_req_done(req);
+}
+
+static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct handle_dnsrpcrec_state *state = tevent_req_data(
+               req, struct handle_dnsrpcrec_state);
+       struct dns_res_rec *answers, *nsrecs, *additional;
+       uint16_t ancount = 0;
+       uint16_t nscount = 0;
+       uint16_t arcount = 0;
+       uint16_t i;
+       WERROR werr;
 
+       werr = ask_forwarder_recv(subreq, state, &answers, &ancount,
+                                 &nsrecs, &nscount, &additional, &arcount);
+       if (tevent_req_werror(req, werr)) {
+               return;
+       }
 
-                       continue;
+       for (i=0; i<ancount; i++) {
+               werr = add_dns_res_rec(state->answers, &answers[i]);
+               if (tevent_req_werror(req, werr)) {
+                       return;
                }
-               if ((question->question_type != DNS_QTYPE_ALL) &&
-                   (recs[ri].wType != (enum dns_record_type) 
question->question_type)) {
-                       werror_return = WERR_OK;
-                       continue;
-               }
-               werror = create_response_rr(question->name, &recs[ri], &ans, 
&ai);
-               if (!W_ERROR_IS_OK(werror)) {
-                       return werror;
+       }
+
+       for (i=0; i<nscount; i++) {
+               werr = add_dns_res_rec(state->nsrecs, &nsrecs[i]);
+               if (tevent_req_werror(req, werr)) {
+                       return;
                }
-               werror_return = WERR_OK;
        }
 
-done:
-       /* Always add an authority record to replies we should know about */
-       add_zone_authority_record(dns, mem_ctx, question, &ns, &ni);
+       tevent_req_done(req);
+}
 
-       *ancount = ai;
-       *answers = ans;
-       *nscount = ni;
-       *nsrecs = ns;
+static WERROR handle_dnsrpcrec_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_werror(req);
+}
+
+struct handle_authoritative_state {
+       struct tevent_context *ev;
+       struct dns_server *dns;
+       struct dns_name_question *question;
+       const char *forwarder;
+
+       struct dnsp_DnssrvRpcRecord *recs;
+       uint16_t rec_count;
+       uint16_t recs_done;
+
+       struct dns_res_rec **answers;
+       struct dns_res_rec **nsrecs;
+};
+
+static void handle_authoritative_done(struct tevent_req *subreq);
+
+static struct tevent_req *handle_authoritative_send(
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct dns_server *dns, const char *forwarder,
+       struct dns_name_question *question,
+       struct dns_res_rec **answers, struct dns_res_rec **nsrecs)
+{
+       struct tevent_req *req, *subreq;
+       struct handle_authoritative_state *state;
+       struct ldb_dn *dn = NULL;
+       WERROR werr;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct handle_authoritative_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->dns = dns;
+       state->question = question;
+       state->forwarder = forwarder;
+       state->answers = answers;
+       state->nsrecs = nsrecs;
+
+       werr = dns_name2dn(dns, state, question->name, &dn);
+       if (tevent_req_werror(req, werr)) {
+               return tevent_req_post(req, ev);
+       }
+
+       werr = dns_lookup_records(dns, state, dn, &state->recs,
+                                 &state->rec_count);
+       TALLOC_FREE(dn);
+       if (tevent_req_werror(req, werr)) {
+               return tevent_req_post(req, ev);
+       }
+
+       if (state->rec_count == 0) {
+               tevent_req_werror(req, DNS_ERR(NAME_ERROR));
+               return tevent_req_post(req, ev);


-- 
Samba Shared Repository

Reply via email to