[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