[SCM] Samba Shared Repository - branch master updated

Kai Blin kai at samba.org
Tue Dec 15 19:28:03 UTC 2015


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 <vl at samba.org>
Date:   Tue Aug 11 07:40:50 2015 +0200

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

commit 6adec9339dee488e41c7552451eca45ebae4b917
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at samba.org>

commit 3b7f99e6f4996cfd97220b3a6d5cceeab6ab5b79
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at samba.org>

commit b6aaf77897082c6ac447e9514260b435ac3ad854
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at samba.org>

commit 4b54e14b7cf456e327b176b365e8471e0899210b
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at samba.org>

commit 3f2cbb616f8b0becf8a3479e72dda11433126e65
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at samba.org>

commit 9de59c7e3f01c578831a8e352ff8e9ee2312c77f
Author: Volker Lendecke <vl at 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 <vl at samba.org>
    Reviewed-by: Kai Blin <kai at 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



More information about the samba-cvs mailing list