[SCM] Samba Shared Repository - branch master updated

Kai Blin kai at samba.org
Tue Mar 27 09:40:02 MDT 2012


The branch, master has been updated
       via  26f7a67 s4 dns: Only do recursive queries when allowed/desired
       via  06dd4d8 s4 dns: Check smb.conf if we should allow recursion
       via  533b2e6 s4 dns: Allow changing the dns operation flags in handlers
       via  8d9da67 s4 dns: Only forward for zones we don't own
       via  a991391 s4 dns: Forward questions we can't answer to another server
       via  10b14fa s4 dns: Add a simple dns lookup helper
       via  7566e6a s4 dns: Add a simple async client library
      from  95ebb11 selftest.py: Add get_interface.

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


- Log -----------------------------------------------------------------
commit 26f7a676f9a0f6f8c5ae3bef9247c675734f35cd
Author: Kai Blin <kai at samba.org>
Date:   Tue Mar 27 15:00:01 2012 +0200

    s4 dns: Only do recursive queries when allowed/desired
    
    If recursive queries are switched off in smb.conf or the client doesn't ask for
    recursion, don't recurse.
    
    Autobuild-User: Kai Blin <kai at samba.org>
    Autobuild-Date: Tue Mar 27 17:39:26 CEST 2012 on sn-devel-104

commit 06dd4d8ee1c5440809fa87fd8a1f3cfac8e9036a
Author: Kai Blin <kai at samba.org>
Date:   Tue Mar 27 14:42:15 2012 +0200

    s4 dns: Check smb.conf if we should allow recursion

commit 533b2e6612bd6497c1d53c31912bccba0260a3e9
Author: Kai Blin <kai at samba.org>
Date:   Tue Mar 27 13:59:03 2012 +0200

    s4 dns: Allow changing the dns operation flags in handlers

commit 8d9da67185aac48d7d0bc1e7b90262ae9afc6a64
Author: Kai Blin <kai at samba.org>
Date:   Tue Mar 27 13:36:16 2012 +0200

    s4 dns: Only forward for zones we don't own

commit a99139160555072339f8f9cc5912c570158fc236
Author: Kai Blin <kai at samba.org>
Date:   Tue Mar 27 08:42:22 2012 +0200

    s4 dns: Forward questions we can't answer to another server
    
    This makes use of libdns and currently hardcodes the forward server, but
    it works. :)

commit 10b14fa1c03fa9d686e94be20a2700954ae090fa
Author: Kai Blin <kai at samba.org>
Date:   Mon Mar 26 20:47:42 2012 +0200

    s4 dns: Add a simple dns lookup helper

commit 7566e6a5347b9d6b2b0b8b27f9211599febd8da1
Author: Kai Blin <kai at samba.org>
Date:   Sun Mar 11 10:13:51 2012 +0100

    s4 dns: Add a simple async client library

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

Summary of changes:
 lib/param/loadparm.c             |   21 +++++
 libcli/dns/dns.c                 |  172 ++++++++++++++++++++++++++++++++++++++
 libcli/dns/libdns.h              |   53 ++++++++++++
 libcli/dns/wscript_build         |    5 +
 source4/dns_server/dns_query.c   |  109 ++++++++++++++++++++++--
 source4/dns_server/dns_server.c  |   21 ++++-
 source4/dns_server/dns_server.h  |    7 ++
 source4/dns_server/dns_update.c  |    1 +
 source4/dns_server/dns_utils.c   |   28 ++++++
 source4/dns_server/wscript_build |    2 +-
 utils/samba-dig.c                |  160 +++++++++++++++++++++++++++++++++++
 utils/wscript_build              |    7 ++
 wscript_build                    |    2 +
 13 files changed, 575 insertions(+), 13 deletions(-)
 create mode 100644 libcli/dns/dns.c
 create mode 100644 libcli/dns/libdns.h
 create mode 100644 libcli/dns/wscript_build
 create mode 100644 utils/samba-dig.c
 create mode 100644 utils/wscript_build


Changeset truncated at 500 lines:

diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index bb59a79..e3792b6 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -1256,6 +1256,22 @@ static struct parm_struct parm_table[] = {
 		.special	= NULL,
 		.enum_list	= enum_dns_update_settings
 	},
+	{
+		.label		= "dns forwarder",
+		.type		= P_STRING,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(dns_forwarder),
+		.special	= NULL,
+		.enum_list	= NULL
+	},
+	{
+		.label		= "dns recursive queries",
+		.type		= P_BOOL,
+		.p_class	= P_GLOBAL,
+		.offset		= GLOBAL_VAR(dns_recursive_queries),
+		.special	= NULL,
+		.enum_list	= NULL
+	},
 
 	{NULL,  P_BOOL,  P_NONE,  0,  NULL,  NULL,  0}
 };
@@ -1536,7 +1552,10 @@ FN_GLOBAL_INTEGER(srv_minprotocol, srv_minprotocol)
 FN_GLOBAL_INTEGER(cli_maxprotocol, cli_maxprotocol)
 FN_GLOBAL_INTEGER(cli_minprotocol, cli_minprotocol)
 FN_GLOBAL_BOOL(paranoid_server_security, paranoid_server_security)
+
 FN_GLOBAL_INTEGER(allow_dns_updates, allow_dns_updates)
+FN_GLOBAL_CONST_STRING(dns_forwarder, dns_forwarder)
+FN_GLOBAL_BOOL(dns_recursive_queries, dns_recursive_queries)
 
 FN_GLOBAL_INTEGER(server_signing, server_signing)
 FN_GLOBAL_INTEGER(client_signing, client_signing)
@@ -3403,6 +3422,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
 
         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "False");
+        lpcfg_do_global_parameter(lp_ctx, "dns recursive queries", "False");
+        lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
 
 	for (i = 0; parm_table[i].label; i++) {
 		if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
diff --git a/libcli/dns/dns.c b/libcli/dns/dns.c
new file mode 100644
index 0000000..ac0c9e4
--- /dev/null
+++ b/libcli/dns/dns.c
@@ -0,0 +1,172 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Small async DNS library for Samba with socketwrapper support
+
+   Copyright (C) 2010 Kai Blin  <kai at samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+#include <tevent.h>
+#include "lib/tsocket/tsocket.h"
+#include "libcli/util/werror.h"
+#include "libcli/dns/libdns.h"
+#include "lib/util/tevent_werror.h"
+#include "lib/util/samba_util.h"
+#include "libcli/util/error.h"
+#include "librpc/gen_ndr/dns.h"
+
+struct dns_udp_request_state {
+	struct tevent_context *ev;
+	struct tdgram_context *dgram;
+	size_t query_len;
+	uint8_t *reply;
+	size_t reply_len;
+};
+
+/* Declare callback functions used below. */
+static void dns_request_get_reply(struct tevent_req *subreq);
+static void dns_request_done(struct tevent_req *subreq);
+
+struct tevent_req *dns_udp_request_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					const char *server_addr_string,
+					const uint8_t *query,
+					size_t query_len)
+{
+	struct tevent_req *req, *subreq;
+	struct dns_udp_request_state *state;
+	struct tsocket_address *local_addr, *server_addr;
+	struct tdgram_context *dgram;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state, struct dns_udp_request_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->ev = ev;
+
+	/* Use connected UDP sockets */
+	ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0,
+						&local_addr);
+	if (ret != 0) {
+		tevent_req_werror(req, unix_to_werror(ret));
+		return tevent_req_post(req, ev);
+	}
+
+	ret = tsocket_address_inet_from_strings(state, "ip", server_addr_string,
+						DNS_SERVICE_PORT, &server_addr);
+	if (ret != 0) {
+		tevent_req_werror(req, unix_to_werror(ret));
+		return tevent_req_post(req, ev);
+	}
+
+	ret = tdgram_inet_udp_socket(local_addr, server_addr, state, &dgram);
+	if (ret != 0) {
+		tevent_req_werror(req, unix_to_werror(ret));
+		return tevent_req_post(req, ev);
+	}
+
+	state->dgram = dgram;
+	state->query_len = query_len;
+
+	dump_data(10, query, query_len);
+
+	subreq = tdgram_sendto_send(state, ev, dgram, query, query_len, NULL);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_set_callback(subreq, dns_request_get_reply, req);
+	return req;
+}
+
+static void dns_request_get_reply(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(subreq,
+						struct tevent_req);
+	struct dns_udp_request_state *state = tevent_req_data(req,
+						struct dns_udp_request_state);
+	ssize_t len;
+	int err = 0;
+
+	len = tdgram_sendto_recv(subreq, &err);
+	TALLOC_FREE(subreq);
+
+	if (len == -1 && err != 0) {
+		tevent_req_werror(req, unix_to_werror(err));
+		return;
+	}
+
+	if (len != state->query_len) {
+		tevent_req_werror(req, WERR_NET_WRITE_FAULT);
+		return;
+	}
+
+	subreq = tdgram_recvfrom_send(state, state->ev, state->dgram);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+
+	tevent_req_set_callback(subreq, dns_request_done, req);
+	return;
+}
+
+static void dns_request_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(subreq,
+						struct tevent_req);
+	struct dns_udp_request_state *state = tevent_req_data(req,
+						struct dns_udp_request_state);
+
+	ssize_t len;
+	int err = 0;
+
+	len = tdgram_recvfrom_recv(subreq, &err, state, &state->reply, NULL);
+	TALLOC_FREE(subreq);
+
+	if (len == -1 && err != 0) {
+		tevent_req_werror(req, unix_to_werror(err));
+		return;
+	}
+
+	state->reply_len = len;
+	dump_data(10, state->reply, state->reply_len);
+	tevent_req_done(req);
+}
+
+WERROR dns_udp_request_recv(struct tevent_req *req,
+			    TALLOC_CTX *mem_ctx,
+			    uint8_t **reply,
+			    size_t *reply_len)
+{
+	struct dns_udp_request_state *state = tevent_req_data(req,
+			struct dns_udp_request_state);
+	WERROR w_error;
+
+	if (tevent_req_is_werror(req, &w_error)) {
+		tevent_req_received(req);
+		return w_error;
+	}
+
+	*reply = talloc_move(mem_ctx, &state->reply);
+	*reply_len = state->reply_len;
+	tevent_req_received(req);
+
+	return WERR_OK;
+}
diff --git a/libcli/dns/libdns.h b/libcli/dns/libdns.h
new file mode 100644
index 0000000..31474eb
--- /dev/null
+++ b/libcli/dns/libdns.h
@@ -0,0 +1,53 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Small async DNS library for Samba with socketwrapper support
+
+   Copyright (C) 2012 Kai Blin  <kai at samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LIBDNS_H__
+#define __LIBDNS_H__
+
+/** Send an dns request to a dns server using UDP
+ *
+ *@param mem_ctx        talloc memory context to use
+ *@param ev             tevent context to use
+ *@param server_address address of the server as a string
+ *@param query          dns query to send
+ *@param query_len      length of the query
+ *@return tevent_req with the active request or NULL on out-of-memory
+ */
+struct tevent_req *dns_udp_request_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					const char *server_address,
+					const uint8_t *query,
+					size_t query_len);
+
+/** Get the dns response from a dns server via UDP
+ *
+ *@param req       tevent_req struct returned from dns_request_send
+ *@param mem_ctx   talloc memory context to use for the reply string
+ *@param reply     buffer that will be allocated and filled with the dns reply
+ *@param reply_len length of the reply buffer
+ *@return WERROR code depending on the async request result
+ */
+WERROR dns_udp_request_recv(struct tevent_req *req,
+			    TALLOC_CTX *mem_ctx,
+			    uint8_t **reply,
+			    size_t *reply_len);
+
+#endif /*__LIBDNS_H__*/
diff --git a/libcli/dns/wscript_build b/libcli/dns/wscript_build
new file mode 100644
index 0000000..2e445da
--- /dev/null
+++ b/libcli/dns/wscript_build
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+bld.SAMBA_SUBSYSTEM('LIBCLI_DNS',
+        source='dns.c',
+        deps='LIBTSOCKET tevent-util')
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 4277659..b3984a4 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -20,14 +20,18 @@
 */
 
 #include "includes.h"
+#include "smbd/service_task.h"
 #include "libcli/util/werror.h"
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_dns.h"
 #include "librpc/gen_ndr/ndr_dnsp.h"
 #include <ldb.h>
+#include "param/param.h"
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/common/util.h"
 #include "dns_server/dns_server.h"
+#include "libcli/dns/libdns.h"
+#include "lib/util/util_net.h"
 
 static WERROR create_response_rr(const struct dns_name_question *question,
 				 const struct dnsp_DnssrvRpcRecord *rec,
@@ -97,6 +101,80 @@ 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 tevent_context *ev = tevent_context_init(mem_ctx);
+	struct dns_name_packet *out_packet, *in_packet;
+	uint16_t id = random();
+	DATA_BLOB out, in;
+	enum ndr_err_code ndr_err;
+	WERROR werr = WERR_OK;
+	struct tevent_req *req;
+	const char *forwarder = lpcfg_dns_forwarder(dns->task->lp_ctx);
+
+	if (!is_ipaddress(forwarder)) {
+		DEBUG(0, ("Invalid 'dns forwarder' setting '%s', needs to be "
+			  "an IP address\n", forwarder));
+		return DNS_ERR(NAME_ERROR);
+	}
+
+	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->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);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return DNS_ERR(SERVER_FAILURE);
+	}
+
+	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);
+	}
+
+	werr = dns_udp_request_recv(req, mem_ctx, &in.data, &in.length);
+	W_ERROR_NOT_OK_RETURN(werr);
+
+	in_packet = talloc_zero(mem_ctx, struct dns_name_packet);
+	W_ERROR_HAVE_NO_MEMORY(in_packet);
+
+	ndr_err = ndr_pull_struct_blob(&in, in_packet, 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);
+	}
+
+	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);
+	}
+
+	*ancount = in_packet->ancount;
+	*answers = talloc_move(mem_ctx, &in_packet->answers);
+
+	*nscount = in_packet->nscount;
+	*nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs);
+
+	*arcount = in_packet->arcount;
+	*additional = talloc_move(mem_ctx, &in_packet->additional);
+
+	return werr;
+}
+
 static WERROR handle_question(struct dns_server *dns,
 			      TALLOC_CTX *mem_ctx,
 			      const struct dns_name_question *question,
@@ -139,14 +217,15 @@ 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)
 {
-	uint16_t num_answers=0;
-	struct dns_res_rec *ans=NULL;
+	uint16_t num_answers=0, num_nsrecs=0, num_additional=0;
+	struct dns_res_rec *ans=NULL, *ns=NULL, *adds=NULL;
 	WERROR werror;
 
 	if (in->qdcount != 1) {
@@ -158,18 +237,34 @@ WERROR dns_server_process_query(struct dns_server *dns,
 		return DNS_ERR(NOT_IMPLEMENTED);
 	}
 
-	werror = handle_question(dns, mem_ctx, &in->questions[0], &ans, &num_answers);
+	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 authorative 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);
+		}
+	}
 	W_ERROR_NOT_OK_GOTO(werror, query_failed);
 
 	*answers = ans;
 	*ancount = num_answers;
 
 	/*FIXME: Do something for these */
-	*nsrecs  = NULL;
-	*nscount = 0;
+	*nsrecs  = ns;
+	*nscount = num_nsrecs;
 
-	*additional = NULL;
-	*arcount    = 0;
+	*additional = adds;
+	*arcount    = num_additional;
 
 	return WERR_OK;
 
diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c
index cf43590..789940f 100644
--- a/source4/dns_server/dns_server.c
+++ b/source4/dns_server/dns_server.c
@@ -100,6 +100,7 @@ static NTSTATUS dns_process(struct dns_server *dns,
 {
 	enum ndr_err_code ndr_err;
 	WERROR ret;
+	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;
@@ -109,9 +110,11 @@ static NTSTATUS dns_process(struct dns_server *dns,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	in_packet = talloc_zero(mem_ctx, struct dns_name_packet);
+	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(mem_ctx, struct dns_name_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;
@@ -134,19 +137,25 @@ static NTSTATUS dns_process(struct dns_server *dns,
 		NDR_PRINT_DEBUG(dns_name_packet, in_packet);
 	}
 	*out_packet = *in_packet;
-	out_packet->operation |= DNS_FLAG_REPLY;
+	state->flags |= in_packet->operation | DNS_FLAG_REPLY;
+
+	if (lpcfg_dns_recursive_queries(dns->task->lp_ctx)) {
+		state->flags |= DNS_FLAG_RECURSION_AVAIL;
+	}
 
 	switch (in_packet->operation & DNS_OPCODE) {
 	case DNS_OPCODE_QUERY:
 
-		ret = dns_server_process_query(dns, out_packet, in_packet,
+		ret = dns_server_process_query(dns, state,
+					       out_packet, in_packet,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list