[SCM] Samba Shared Repository - branch master updated - c8565c0e7acc6febf1b4015bde6baa1c5b7adddc

Stefan Metzmacher metze at samba.org
Wed Dec 17 18:45:57 GMT 2008


The branch, master has been updated
       via  c8565c0e7acc6febf1b4015bde6baa1c5b7adddc (commit)
       via  f6b3c70b9728484106eb09a5f53425227bb1b288 (commit)
       via  9492f0f00fd7c1815959f19988f83accce108ce4 (commit)
       via  8df2140c18996e616e6fe1fcc8fd3e52ca5dcd74 (commit)
       via  372f700f4756b4c3d0a79dc4aa4be3ec0c9dc29d (commit)
       via  03acd2912847ba49d50d865662519ac24b9abe4c (commit)
      from  fa23a63b4d290ba81a593adad1b6a6612bdb3b93 (commit)

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


- Log -----------------------------------------------------------------
commit c8565c0e7acc6febf1b4015bde6baa1c5b7adddc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Dec 13 10:57:44 2008 +0100

    s4:libcli/resolve: remove all backend specific sync functions
    
    metze

commit f6b3c70b9728484106eb09a5f53425227bb1b288
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 12 19:40:47 2008 +0100

    s4:libcli/resolve: let the "host" module use the dns_ex.c code
    
    That means we now return all ip addresses instead of just the first one.
    
    metze

commit 9492f0f00fd7c1815959f19988f83accce108ce4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 12 15:15:21 2008 +0100

    s4:libcli/resolve: add getaddrinfo()/dns_looup() resolving
    
    This "dns_ex" module provides flexible lookup methods
    for dns lookups.
    
    The getaddrinfo() part looks at /etc/hosts and dns.
    As it handles CNAME replies badly we fallback
    to use dns_lookup(name, "A").
    
    The dns_lookup() makes DNS SRV lookups possible.
    
    This module is not a real resolve module, it's just
    a generic helper as the nbtlist.c code is.
    
    The next step will be that the "host" module will
    use the dns_ex.c code.
    
    metze

commit 8df2140c18996e616e6fe1fcc8fd3e52ca5dcd74
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Dec 13 11:24:10 2008 +0100

    s4:libcli/resolve: don't use __RESOLVE_H__ it might be used by system headers too
    
    metze

commit 372f700f4756b4c3d0a79dc4aa4be3ec0c9dc29d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 12 14:36:15 2008 +0100

    s4:lib/socket: we need to lookup the #20 netbios name when we connect to a remote server
    
    metze

commit 03acd2912847ba49d50d865662519ac24b9abe4c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 12 14:35:42 2008 +0100

    s4:lib/socket: remove unused code
    
    metze

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

Summary of changes:
 source4/lib/socket/connect.c       |   24 +--
 source4/lib/socket/connect_multi.c |    2 +-
 source4/libcli/config.mk           |    1 +
 source4/libcli/resolve/bcast.c     |   20 --
 source4/libcli/resolve/dns_ex.c    |  484 ++++++++++++++++++++++++++++++++++++
 source4/libcli/resolve/host.c      |  203 +--------------
 source4/libcli/resolve/nbtlist.c   |   20 --
 source4/libcli/resolve/resolve.c   |   13 -
 source4/libcli/resolve/resolve.h   |    6 +-
 source4/libcli/resolve/wins.c      |   21 --
 10 files changed, 500 insertions(+), 294 deletions(-)
 create mode 100644 source4/libcli/resolve/dns_ex.c


Changeset truncated at 500 lines:

diff --git a/source4/lib/socket/connect.c b/source4/lib/socket/connect.c
index 2b64668..409e19e 100644
--- a/source4/lib/socket/connect.c
+++ b/source4/lib/socket/connect.c
@@ -39,25 +39,16 @@ static void socket_connect_handler(struct event_context *ev,
 				   struct fd_event *fde, 
 				   uint16_t flags, void *private);
 static void continue_resolve_name(struct composite_context *ctx);
-static void continue_socket_connect(struct composite_context *creq);
 
 /*
   call the real socket_connect() call, and setup event handler
 */
 static void socket_send_connect(struct composite_context *result)
 {
-	struct composite_context *creq;
 	struct fd_event *fde;
 	struct connect_state *state = talloc_get_type(result->private_data, 
 						      struct connect_state);
 
-	creq = talloc_zero(state, struct composite_context);
-	if (composite_nomem(creq, result)) return;
-	creq->state = COMPOSITE_STATE_IN_PROGRESS;
-	creq->event_ctx = result->event_ctx;
-	creq->async.fn = continue_socket_connect;
-	creq->async.private_data = result;
-
 	result->status = socket_connect(state->sock,
 					state->my_address,
 					state->server_address,
@@ -125,7 +116,7 @@ struct composite_context *socket_connect_send(struct socket_context *sock,
 	if (resolve_ctx != NULL && server_address->addr && strcmp(sock->backend_name, "ipv4") == 0) {
 		struct nbt_name name;
 		struct composite_context *creq;
-		make_nbt_name_client(&name, server_address->addr);
+		make_nbt_name_server(&name, server_address->addr);
 		creq = resolve_name_send(resolve_ctx, &name, result->event_ctx);
 		if (composite_nomem(creq, result)) return result;
 		composite_continue(result, creq, continue_resolve_name, result);
@@ -176,19 +167,6 @@ static void continue_resolve_name(struct composite_context *creq)
 }
 
 /*
-  called when a connect has finished. Complete the top level composite context
-*/
-static void continue_socket_connect(struct composite_context *creq)
-{
-	struct composite_context *result = talloc_get_type(creq->async.private_data, 
-							   struct composite_context);
-	result->status = creq->status;
-	if (!composite_is_ok(result)) return;
-	composite_done(result);
-}
-
-
-/*
   wait for a socket_connect_send() to finish
 */
 NTSTATUS socket_connect_recv(struct composite_context *result)
diff --git a/source4/lib/socket/connect_multi.c b/source4/lib/socket/connect_multi.c
index 98b4d40..ad8637a 100644
--- a/source4/lib/socket/connect_multi.c
+++ b/source4/lib/socket/connect_multi.c
@@ -105,7 +105,7 @@ _PUBLIC_ struct composite_context *socket_connect_multi_send(
 		 */
 		struct nbt_name name;
 		struct composite_context *creq;
-		make_nbt_name_client(&name, server_address);
+		make_nbt_name_server(&name, server_address);
 		creq = resolve_name_send(resolve_ctx, &name, result->event_ctx);
 		if (composite_nomem(creq, result)) goto failed;
 		composite_continue(result, creq, continue_resolve_name, result);
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index 8c31077..b60cda9 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -136,6 +136,7 @@ PRIVATE_DEPENDENCIES = LIBCLI_NBT LIBSAMBA-HOSTCONFIG LIBNETIF
 
 LP_RESOLVE_OBJ_FILES = $(addprefix $(libclisrcdir)/resolve/, \
 					  bcast.o nbtlist.o wins.o \
+					  dns_ex.o \
 					  host.o resolve_lp.o)
 
 $(eval $(call proto_header_template,$(libclisrcdir)/resolve/lp_proto.h,$(LP_RESOLVE_OBJ_FILES:.o=.c)))
diff --git a/source4/libcli/resolve/bcast.c b/source4/libcli/resolve/bcast.c
index 0a71ebe..a572e87 100644
--- a/source4/libcli/resolve/bcast.c
+++ b/source4/libcli/resolve/bcast.c
@@ -85,26 +85,6 @@ NTSTATUS resolve_name_bcast_recv(struct composite_context *c,
 	return status;
 }
 
-/*
-  broadcast name resolution method - sync call
- */
-NTSTATUS resolve_name_bcast(struct nbt_name *name, 
-			    TALLOC_CTX *mem_ctx,
-			    struct interface *ifaces,
-			    uint16_t nbt_port,
-			    int nbt_timeout,
-			    struct socket_address ***addrs)
-{
-	struct resolve_bcast_data *data = talloc(mem_ctx, struct resolve_bcast_data);
-	struct composite_context *c;
-	data->ifaces = talloc_reference(data, ifaces);
-	data->nbt_port = nbt_port;
-	data->nbt_timeout = nbt_timeout;
-	
-	c = resolve_name_bcast_send(mem_ctx, NULL, data, name);
-	return resolve_name_bcast_recv(c, mem_ctx, addrs);
-}
-
 bool resolve_context_add_bcast_method(struct resolve_context *ctx, struct interface *ifaces, uint16_t nbt_port, int nbt_timeout)
 {
 	struct resolve_bcast_data *data = talloc(ctx, struct resolve_bcast_data);
diff --git a/source4/libcli/resolve/dns_ex.c b/source4/libcli/resolve/dns_ex.c
new file mode 100644
index 0000000..4bcf50a
--- /dev/null
+++ b/source4/libcli/resolve/dns_ex.c
@@ -0,0 +1,484 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   async getaddrinfo()/dns_lookup() name resolution module
+
+   Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Stefan Metzmacher 2008
+
+   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/>.
+*/
+
+/*
+  this module uses a fork() per getaddrinfo() or dns_looup() call.
+  At first that might seem crazy, but it is actually very fast,
+  and solves many of the tricky problems of keeping a child
+  hanging around in a librar (like what happens when the parent forks).
+  We use a talloc destructor to ensure that the child is cleaned up
+  when we have finished with this name resolution.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "system/network.h"
+#include "system/filesys.h"
+#include "lib/socket/socket.h"
+#include "libcli/composite/composite.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "libcli/resolve/resolve.h"
+#include "heimdal/lib/roken/resolve.h"
+
+struct dns_ex_state {
+	bool do_getaddrinfo;
+	bool do_fallback;
+	bool do_srv;
+	struct nbt_name name;
+	struct socket_address **addrs;
+	pid_t child;
+	int child_fd;
+	struct fd_event *fde;
+	struct event_context *event_ctx;
+};
+
+/*
+  kill off a wayward child if needed. This allows us to stop an async
+  name resolution without leaving a potentially blocking call running
+  in a child
+*/
+static int dns_ex_destructor(struct dns_ex_state *state)
+{
+	int status;
+
+	kill(state->child, SIGTERM);
+	close(state->child_fd);
+	if (waitpid(state->child, &status, WNOHANG) == 0) {
+		kill(state->child, SIGKILL);
+		waitpid(state->child, &status, 0);
+	}
+
+	return 0;
+}
+
+/*
+  the blocking child
+*/
+static void run_child_dns_lookup(struct dns_ex_state *state, int fd)
+{
+	struct dns_reply *reply;
+	struct resource_record *rr;
+	uint32_t count = 0;
+	uint32_t srv_valid = 0;
+	struct resource_record **srv_rr;
+	uint32_t addrs_valid = 0;
+	struct resource_record **addrs_rr;
+	char *addrs;
+	bool first;
+	uint32_t i;
+
+	/* this is the blocking call we are going to lots of trouble
+	   to avoid in the parent */
+	reply = dns_lookup(state->name.name, state->do_srv?"SRV":"A");
+	if (!reply) {
+		goto done;
+	}
+
+	if (state->do_srv) {
+		dns_srv_order(reply);
+	}
+
+	/* Loop over all returned records and pick the "srv" records */
+	for (rr=reply->head; rr; rr=rr->next) {
+		/* we are only interested in the IN class */
+		if (rr->class != C_IN) {
+			continue;
+		}
+
+		if (state->do_srv) {
+			/* we are only interested in SRV records */
+			if (rr->type != T_SRV) {
+				continue;
+			}
+
+			/* verify we actually have a SRV record here */
+			if (!rr->u.srv) {
+				continue;
+			}
+
+			/* Verify we got a port */
+			if (rr->u.srv->port == 0) {
+				continue;
+			}
+		} else {
+			/* we are only interested in A records */
+			/* TODO: add AAAA support */
+			if (rr->type != T_A) {
+				continue;
+			}
+
+			/* verify we actually have a A record here */
+			if (!rr->u.a) {
+				continue;
+			}
+		}
+		count++;
+	}
+
+	if (count == 0) {
+		goto done;
+	}
+
+	srv_rr = talloc_zero_array(state,
+				   struct resource_record *,
+				   count);
+	if (!srv_rr) {
+		goto done;
+	}
+
+	addrs_rr = talloc_zero_array(state,
+				     struct resource_record *,
+				     count);
+	if (!addrs_rr) {
+		goto done;
+	}
+
+	/* Loop over all returned records and pick the records */
+	for (rr=reply->head;rr;rr=rr->next) {
+		/* we are only interested in the IN class */
+		if (rr->class != C_IN) {
+			continue;
+		}
+
+		if (state->do_srv) {
+			/* we are only interested in SRV records */
+			if (rr->type != T_SRV) {
+				continue;
+			}
+
+			/* verify we actually have a srv record here */
+			if (!rr->u.srv) {
+				continue;
+			}
+
+			/* Verify we got a port */
+			if (rr->u.srv->port == 0) {
+				continue;
+			}
+
+			srv_rr[srv_valid] = rr;
+			srv_valid++;
+		} else {
+			/* we are only interested in A records */
+			/* TODO: add AAAA support */
+			if (rr->type != T_A) {
+				continue;
+			}
+
+			/* verify we actually have a A record here */
+			if (!rr->u.a) {
+				continue;
+			}
+
+			addrs_rr[addrs_valid] = rr;
+			addrs_valid++;
+		}
+	}
+
+	for (i=0; i < srv_valid; i++) {
+		for (rr=reply->head;rr;rr=rr->next) {
+
+			if (rr->class != C_IN) {
+				continue;
+			}
+
+			/* we are only interested in SRV records */
+			if (rr->type != T_A) {
+				continue;
+			}
+
+			/* verify we actually have a srv record here */
+			if (strcmp(&srv_rr[i]->u.srv->target[0], rr->domain) != 0) {
+				continue;
+			}
+
+			addrs_rr[i] = rr;
+			addrs_valid++;
+			break;
+		}
+	}
+
+	if (addrs_valid == 0) {
+		goto done;
+	}
+
+	addrs = talloc_strdup(state, "");
+	if (!addrs) {
+		goto done;
+	}
+	first = true;
+	for (i=0; i < count; i++) {
+		if (!addrs_rr[i]) {
+			continue;
+		}
+		addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u",
+						      first?"":",",
+						      inet_ntoa(*addrs_rr[i]->u.a),
+						      srv_rr[i]?srv_rr[i]->u.srv->port:0);
+		if (!addrs) {
+			goto done;
+		}
+		first = false;
+	}
+
+	if (addrs) {
+		write(fd, addrs, talloc_get_size(addrs));
+	}
+
+done:
+	close(fd);
+}
+
+/*
+  the blocking child
+*/
+static void run_child_getaddrinfo(struct dns_ex_state *state, int fd)
+{
+	int ret;
+	struct addrinfo hints;
+	struct addrinfo *res;
+	struct addrinfo *res_list = NULL;
+	char *addrs;
+	bool first;
+
+	ZERO_STRUCT(hints);
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_family = AF_INET;/* TODO: add AF_INET6 support */
+	hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+
+	ret = getaddrinfo(state->name.name, "0", &hints, &res_list);
+	if (ret == EAI_NODATA && state->do_fallback) {
+		/* getaddrinfo() doesn't handle CNAME records */
+		run_child_dns_lookup(state, fd);
+		return;
+	}
+	if (ret != 0) {
+		goto done;
+	}
+
+	addrs = talloc_strdup(state, "");
+	if (!addrs) {
+		goto done;
+	}
+	first = true;
+	for (res = res_list; res; res = res->ai_next) {
+		struct sockaddr_in *in;
+
+		if (res->ai_family != AF_INET) {
+			continue;
+		}
+		in = (struct sockaddr_in *)res->ai_addr;
+
+		addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u",
+						      first?"":",",
+						      inet_ntoa(in->sin_addr),
+						      0);
+		if (!addrs) {
+			goto done;
+		}
+		first = false;
+	}
+
+	if (addrs) {
+		write(fd, addrs, talloc_get_size(addrs));
+	}
+done:
+	if (res_list) {
+		freeaddrinfo(res_list);
+	}
+	close(fd);
+}
+
+/*
+  handle a read event on the pipe
+*/
+static void pipe_handler(struct event_context *ev, struct fd_event *fde, 
+			 uint16_t flags, void *private_data)
+{
+	struct composite_context *c = talloc_get_type(private_data, struct composite_context);
+	struct dns_ex_state *state = talloc_get_type(c->private_data,
+				     struct dns_ex_state);
+	char address[2048];
+	uint32_t num_addrs, i;
+	char **addrs;
+	int ret;
+	int status;
+
+	/* if we get any event from the child then we know that we
+	   won't need to kill it off */
+	talloc_set_destructor(state, NULL);
+
+	/* yes, we don't care about EAGAIN or other niceities
+	   here. They just can't happen with this parent/child
+	   relationship, and even if they did then giving an error is
+	   the right thing to do */
+	ret = read(state->child_fd, address, sizeof(address)-1);
+	close(state->child_fd);
+	if (waitpid(state->child, &status, WNOHANG) == 0) {
+		kill(state->child, SIGKILL);
+		waitpid(state->child, &status, 0);
+	}
+
+	if (ret <= 0) {
+		composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+		return;
+	}
+
+	/* enusre the address looks good */
+	address[ret] = 0;
+
+	addrs = str_list_make(state, address, ",");
+	if (composite_nomem(addrs, c)) return;
+
+	num_addrs = str_list_length((const char * const *)addrs);
+
+	state->addrs = talloc_array(state, struct socket_address *,
+				    num_addrs+1);
+	if (composite_nomem(state->addrs, c)) return;
+
+	for (i=0; i < num_addrs; i++) {
+		uint32_t port = 0;
+		char *p = strrchr(addrs[i], ':');
+
+		if (!p) {
+			composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+			return;
+		}
+
+		*p = '\0';
+		p++;
+
+		if (strcmp(addrs[i], "0.0.0.0") == 0 ||
+		    inet_addr(addrs[i]) == INADDR_NONE) {
+			composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+			return;
+		}
+		port = strtoul(p, NULL, 10);
+		if (port > UINT16_MAX) {
+			port = 0;
+		}
+		state->addrs[i] = socket_address_from_strings(state->addrs,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list