From 7d0e78a52cfed797100696725611655227cf01ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 13 Dec 2008 20:50:36 +0100 Subject: s4:libcli/resolve: optionally return the name that belongs to the returned address E.g. this helps for DNS CNAME and SRV results. metze --- source4/libcli/resolve/bcast.c | 5 ++-- source4/libcli/resolve/dns_ex.c | 55 ++++++++++++++++++++++++++++++-------- source4/libcli/resolve/host.c | 5 ++-- source4/libcli/resolve/nbtlist.c | 14 +++++++++- source4/libcli/resolve/resolve.c | 16 ++++++++--- source4/libcli/resolve/resolve.h | 3 ++- source4/libcli/resolve/testsuite.c | 2 +- source4/libcli/resolve/wins.c | 5 ++-- 8 files changed, 82 insertions(+), 23 deletions(-) (limited to 'source4/libcli') diff --git a/source4/libcli/resolve/bcast.c b/source4/libcli/resolve/bcast.c index 285a612fb1..23c8e0ca56 100644 --- a/source4/libcli/resolve/bcast.c +++ b/source4/libcli/resolve/bcast.c @@ -76,9 +76,10 @@ struct composite_context *resolve_name_bcast_send(TALLOC_CTX *mem_ctx, */ NTSTATUS resolve_name_bcast_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { - NTSTATUS status = resolve_name_nbtlist_recv(c, mem_ctx, addrs); + NTSTATUS status = resolve_name_nbtlist_recv(c, mem_ctx, addrs, names); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { /* this makes much more sense for a bcast name resolution timeout */ diff --git a/source4/libcli/resolve/dns_ex.c b/source4/libcli/resolve/dns_ex.c index 36d7269be4..cfe4531654 100644 --- a/source4/libcli/resolve/dns_ex.c +++ b/source4/libcli/resolve/dns_ex.c @@ -46,6 +46,7 @@ struct dns_ex_state { uint32_t flags; struct nbt_name name; struct socket_address **addrs; + char **names; pid_t child; int child_fd; struct fd_event *fde; @@ -231,10 +232,11 @@ static void run_child_dns_lookup(struct dns_ex_state *state, int fd) if (!addrs_rr[i]) { continue; } - addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u", + addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u/%s", first?"":",", inet_ntoa(*addrs_rr[i]->u.a), - srv_rr[i]?srv_rr[i]->u.srv->port:0); + srv_rr[i]?srv_rr[i]->u.srv->port:0, + addrs_rr[i]->domain); if (!addrs) { goto done; } @@ -289,10 +291,10 @@ static void run_child_getaddrinfo(struct dns_ex_state *state, int fd) } in = (struct sockaddr_in *)res->ai_addr; - addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u", + addrs = talloc_asprintf_append_buffer(addrs, "%s%s:%u/%s", first?"":",", inet_ntoa(in->sin_addr), - 0); + 0, state->name.name); if (!addrs) { goto done; } @@ -318,21 +320,31 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, 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]; + char *address; uint32_t num_addrs, i; char **addrs; int ret; int status; + int value = 0; /* 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); + if (ioctl(state->child_fd, FIONREAD, &value) != 0) { + value = 8192; + } + + address = talloc_array(state, char, value+1); + if (address) { + /* 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, value); + } else { + ret = -1; + } close(state->child_fd); if (waitpid(state->child, &status, WNOHANG) == 0) { kill(state->child, SIGKILL); @@ -356,9 +368,13 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, num_addrs+1); if (composite_nomem(state->addrs, c)) return; + state->names = talloc_array(state, char *, num_addrs+1); + if (composite_nomem(state->names, c)) return; + for (i=0; i < num_addrs; i++) { uint32_t port = 0; char *p = strrchr(addrs[i], ':'); + char *n; if (!p) { composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND); @@ -368,6 +384,15 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, *p = '\0'; p++; + n = strrchr(p, '/'); + if (!n) { + composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND); + return; + } + + *n = '\0'; + n++; + if (strcmp(addrs[i], "0.0.0.0") == 0 || inet_addr(addrs[i]) == INADDR_NONE) { composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND); @@ -382,8 +407,12 @@ static void pipe_handler(struct event_context *ev, struct fd_event *fde, addrs[i], port); if (composite_nomem(state->addrs[i], c)) return; + + state->names[i] = talloc_strdup(state->names, n); + if (composite_nomem(state->names[i], c)) return; } state->addrs[i] = NULL; + state->names[i] = NULL; composite_done(c); } @@ -470,7 +499,8 @@ struct composite_context *resolve_name_dns_ex_send(TALLOC_CTX *mem_ctx, */ NTSTATUS resolve_name_dns_ex_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { NTSTATUS status; @@ -480,6 +510,9 @@ NTSTATUS resolve_name_dns_ex_recv(struct composite_context *c, struct dns_ex_state *state = talloc_get_type(c->private_data, struct dns_ex_state); *addrs = talloc_steal(mem_ctx, state->addrs); + if (names) { + *names = talloc_steal(mem_ctx, state->names); + } } talloc_free(c); diff --git a/source4/libcli/resolve/host.c b/source4/libcli/resolve/host.c index 1ad1473e92..d85c63b5d3 100644 --- a/source4/libcli/resolve/host.c +++ b/source4/libcli/resolve/host.c @@ -46,9 +46,10 @@ struct composite_context *resolve_name_host_send(TALLOC_CTX *mem_ctx, */ NTSTATUS resolve_name_host_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { - return resolve_name_dns_ex_recv(c, mem_ctx, addrs); + return resolve_name_dns_ex_recv(c, mem_ctx, addrs, names); } bool resolve_context_add_host_method(struct resolve_context *ctx) diff --git a/source4/libcli/resolve/nbtlist.c b/source4/libcli/resolve/nbtlist.c index 962dd420ab..8d6a5a7a7e 100644 --- a/source4/libcli/resolve/nbtlist.c +++ b/source4/libcli/resolve/nbtlist.c @@ -41,6 +41,7 @@ struct nbtlist_state { struct nbt_name_request **queries; struct nbt_name_query *io_queries; struct socket_address **addrs; + char **names; struct interface *ifaces; }; @@ -82,14 +83,21 @@ static void nbtlist_handler(struct nbt_name_request *req) q->out.num_addrs + 1); if (composite_nomem(state->addrs, c)) return; + state->names = talloc_array(state, char *, q->out.num_addrs + 1); + if (composite_nomem(state->names, c)) return; + for (i=0;iout.num_addrs;i++) { state->addrs[i] = socket_address_from_strings(state->addrs, "ipv4", q->out.reply_addrs[i], 0); if (composite_nomem(state->addrs[i], c)) return; + + state->names[i] = talloc_strdup(state->names, state->name.name); + if (composite_nomem(state->names[i], c)) return; } state->addrs[i] = NULL; + state->names[i] = NULL; composite_done(c); } @@ -184,7 +192,8 @@ struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx, */ NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { NTSTATUS status; @@ -193,6 +202,9 @@ NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c, if (NT_STATUS_IS_OK(status)) { struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state); *addrs = talloc_steal(mem_ctx, state->addrs); + if (names) { + *names = talloc_steal(mem_ctx, state->names); + } } talloc_free(c); diff --git a/source4/libcli/resolve/resolve.c b/source4/libcli/resolve/resolve.c index 072eeabb7a..b688dc7a76 100644 --- a/source4/libcli/resolve/resolve.c +++ b/source4/libcli/resolve/resolve.c @@ -35,6 +35,7 @@ struct resolve_state { struct nbt_name name; struct composite_context *creq; struct socket_address **addrs; + char **names; }; static struct composite_context *setup_next_method(struct composite_context *c); @@ -84,7 +85,7 @@ static void resolve_handler(struct composite_context *creq) struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state); const struct resolve_method *method = state->method; - c->status = method->recv_fn(creq, state, &state->addrs); + c->status = method->recv_fn(creq, state, &state->addrs, &state->names); if (!NT_STATUS_IS_OK(c->status)) { state->method = state->method->next; @@ -171,6 +172,11 @@ struct composite_context *resolve_name_all_send(struct resolve_context *ctx, inet_ntoa(ip), 0); if (composite_nomem(state->addrs[0], c)) return c; state->addrs[1] = NULL; + state->names = talloc_array(state, char *, 2); + if (composite_nomem(state->names, c)) return c; + state->names[0] = talloc_strdup(state->names, state->name.name); + if (composite_nomem(state->names[0], c)) return c; + state->names[1] = NULL; composite_done(c); return c; } @@ -191,7 +197,8 @@ struct composite_context *resolve_name_all_send(struct resolve_context *ctx, */ NTSTATUS resolve_name_all_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { NTSTATUS status; @@ -200,6 +207,9 @@ NTSTATUS resolve_name_all_recv(struct composite_context *c, if (NT_STATUS_IS_OK(status)) { struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state); *addrs = talloc_steal(mem_ctx, state->addrs); + if (names) { + *names = talloc_steal(mem_ctx, state->names); + } } talloc_free(c); @@ -220,7 +230,7 @@ NTSTATUS resolve_name_recv(struct composite_context *c, NTSTATUS status; struct socket_address **addrs = NULL; - status = resolve_name_all_recv(c, mem_ctx, &addrs); + status = resolve_name_all_recv(c, mem_ctx, &addrs, NULL); if (NT_STATUS_IS_OK(status)) { *reply_addr = talloc_steal(mem_ctx, addrs[0]->addr); diff --git a/source4/libcli/resolve/resolve.h b/source4/libcli/resolve/resolve.h index 9808b81393..344307febb 100644 --- a/source4/libcli/resolve/resolve.h +++ b/source4/libcli/resolve/resolve.h @@ -33,7 +33,8 @@ typedef struct composite_context *(*resolve_name_send_fn)(TALLOC_CTX *mem_ctx, struct nbt_name *); typedef NTSTATUS (*resolve_name_recv_fn)(struct composite_context *creq, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs); + struct socket_address ***addrs, + char ***names); #include "libcli/resolve/proto.h" struct interface; #include "libcli/resolve/lp_proto.h" diff --git a/source4/libcli/resolve/testsuite.c b/source4/libcli/resolve/testsuite.c index 7e002bd310..ded1d1c9c1 100644 --- a/source4/libcli/resolve/testsuite.c +++ b/source4/libcli/resolve/testsuite.c @@ -46,7 +46,7 @@ static bool test_async_resolve(struct torture_context *tctx) struct socket_address **s; struct composite_context *c = resolve_name_host_send(mem_ctx, ev, NULL, 0, &n); torture_assert(tctx, c != NULL, "resolve_name_host_send"); - torture_assert_ntstatus_ok(tctx, resolve_name_host_recv(c, mem_ctx, &s), + torture_assert_ntstatus_ok(tctx, resolve_name_host_recv(c, mem_ctx, &s, NULL), "async resolve failed"); count++; } diff --git a/source4/libcli/resolve/wins.c b/source4/libcli/resolve/wins.c index 31e6b9e75c..c560d94a8d 100644 --- a/source4/libcli/resolve/wins.c +++ b/source4/libcli/resolve/wins.c @@ -56,9 +56,10 @@ struct composite_context *resolve_name_wins_send( */ NTSTATUS resolve_name_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct socket_address ***addrs) + struct socket_address ***addrs, + char ***names) { - return resolve_name_nbtlist_recv(c, mem_ctx, addrs); + return resolve_name_nbtlist_recv(c, mem_ctx, addrs, names); } bool resolve_context_add_wins_method(struct resolve_context *ctx, const char **address_list, struct interface *ifaces, uint16_t nbt_port, int nbt_timeout) -- cgit