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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
*/
#include "includes.h"
-#include "events.h"
+#include "lib/events/events.h"
#include "system/network.h"
-#include "libcli/raw/libcliraw.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"
struct host_state {
struct nbt_name name;
- const char *reply_addr;
+ struct socket_address **addrs;
pid_t child;
int child_fd;
struct fd_event *fde;
name resolution without leaving a potentially blocking call running
in a child
*/
-static int host_destructor(void *ptr)
+static int host_destructor(struct host_state *state)
{
- struct host_state *state = talloc_get_type(ptr, struct host_state);
+ int status;
+
+ kill(state->child, SIGTERM);
close(state->child_fd);
- if (state->child != (pid_t)-1) {
- kill(state->child, SIGTERM);
+ 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(struct smbcli_composite *c, int fd)
+static void run_child(struct composite_context *c, int fd)
{
- struct host_state *state = talloc_get_type(c->private, struct host_state);
- struct ipv4_addr ip;
+ struct host_state *state = talloc_get_type(c->private_data, struct host_state);
+ struct in_addr ip;
const char *address;
/* this is the blocking call we are going to lots of trouble
to avoid in the parent */
ip = interpret_addr2(state->name.name);
- address = sys_inet_ntoa(ip);
+ address = inet_ntoa(ip);
if (address != NULL) {
write(fd, address, strlen(address)+1);
}
+ close(fd);
}
/*
handle a read event on the pipe
*/
static void pipe_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ uint16_t flags, void *private_data)
{
- struct smbcli_composite *c = talloc_get_type(fde->private, struct smbcli_composite);
- struct host_state *state = talloc_get_type(c->private, struct host_state);
+ struct composite_context *c = talloc_get_type(private_data, struct composite_context);
+ struct host_state *state = talloc_get_type(c->private_data, struct host_state);
char address[128];
int ret;
+ int status;
/* if we get any event from the child then we know that we
won't need to kill it off */
- state->child = (pid_t)-1;
+ 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 (ret <= 0) goto failed;
+ 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;
if (strcmp(address, "0.0.0.0") == 0 ||
- sys_inet_addr(address) == INADDR_NONE) {
- goto failed;
+ inet_addr(address) == INADDR_NONE) {
+ composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ return;
}
- state->reply_addr = talloc_strdup(state, address);
- if (state->reply_addr == NULL) goto failed;
+ state->addrs = talloc_array(state, struct socket_address *, 2);
+ if (composite_nomem(state->addrs, c)) return;
- c->status = NT_STATUS_OK;
- c->state = SMBCLI_REQUEST_DONE;
- if (c->async.fn) {
- c->async.fn(c);
- }
- return;
+ state->addrs[0] = socket_address_from_strings(state->addrs,
+ "ipv4",
+ address,
+ 0);
+ if (composite_nomem(state->addrs[0], c)) return;
+ state->addrs[1] = NULL;
-failed:
- c->status = NT_STATUS_BAD_NETWORK_NAME;
- c->state = SMBCLI_REQUEST_ERROR;
- if (c->async.fn) {
- c->async.fn(c);
- }
+ composite_done(c);
}
/*
gethostbyname name resolution method - async send
*/
-struct smbcli_composite *resolve_name_host_send(struct nbt_name *name,
- struct event_context *event_ctx)
+struct composite_context *resolve_name_host_send(TALLOC_CTX *mem_ctx,
+ struct event_context *event_ctx,
+ void *privdata,
+ struct nbt_name *name)
{
- struct smbcli_composite *c;
+ struct composite_context *c;
struct host_state *state;
- NTSTATUS status;
int fd[2] = { -1, -1 };
- struct fd_event fde;
int ret;
- c = talloc_zero(NULL, struct smbcli_composite);
- if (c == NULL) goto failed;
+ c = composite_create(mem_ctx, event_ctx);
+ if (c == NULL) return NULL;
- state = talloc(c, struct host_state);
- if (state == NULL) goto failed;
+ if (composite_nomem(c->event_ctx, c)) return c;
- status = nbt_name_dup(state, name, &state->name);
- if (!NT_STATUS_IS_OK(status)) goto failed;
+ state = talloc(c, struct host_state);
+ if (composite_nomem(state, c)) return c;
+ c->private_data = state;
- c->state = SMBCLI_REQUEST_SEND;
- c->private = state;
- c->event_ctx = talloc_reference(c, event_ctx);
+ c->status = nbt_name_dup(state, name, &state->name);
+ if (!composite_is_ok(c)) return c;
/* setup a pipe to chat to our child */
ret = pipe(fd);
- if (ret == -1) goto failed;
+ if (ret == -1) {
+ composite_error(c, map_nt_error_from_unix(errno));
+ return c;
+ }
state->child_fd = fd[0];
state->event_ctx = c->event_ctx;
/* we need to put the child in our event context so
we know when the gethostbyname() has finished */
- fde.fd = state->child_fd;
- fde.flags = EVENT_FD_READ;
- fde.handler = pipe_handler;
- fde.private = c;
- state->fde = event_add_fd(c->event_ctx, &fde, state);
- if (state->fde == NULL) {
+ state->fde = event_add_fd(c->event_ctx, c, state->child_fd, EVENT_FD_READ,
+ pipe_handler, c);
+ if (composite_nomem(state->fde, c)) {
close(fd[0]);
close(fd[1]);
- goto failed;
+ return c;
}
- /* signal handling in posix really sucks - doing this in a library
- affects the whole app, but what else to do?? */
- signal(SIGCHLD, SIG_IGN);
-
state->child = fork();
if (state->child == (pid_t)-1) {
- goto failed;
+ composite_error(c, map_nt_error_from_unix(errno));
+ return c;
}
+
if (state->child == 0) {
close(fd[0]);
run_child(c, fd[1]);
/* cleanup wayward children */
talloc_set_destructor(state, host_destructor);
- return c;
-
-failed:
- talloc_free(c);
- return NULL;
+ return c;
}
/*
gethostbyname name resolution method - recv side
*/
-NTSTATUS resolve_name_host_recv(struct smbcli_composite *c,
- TALLOC_CTX *mem_ctx, const char **reply_addr)
+NTSTATUS resolve_name_host_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct socket_address ***addrs)
{
NTSTATUS status;
- status = smb_composite_wait(c);
+ status = composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
- struct host_state *state = talloc_get_type(c->private, struct host_state);
- *reply_addr = talloc_steal(mem_ctx, state->reply_addr);
+ struct host_state *state = talloc_get_type(c->private_data, struct host_state);
+ *addrs = talloc_steal(mem_ctx, state->addrs);
}
talloc_free(c);
*/
NTSTATUS resolve_name_host(struct nbt_name *name,
TALLOC_CTX *mem_ctx,
- const char **reply_addr)
+ struct socket_address ***addrs)
{
- struct smbcli_composite *c = resolve_name_host_send(name, NULL);
- return resolve_name_host_recv(c, mem_ctx, reply_addr);
+ struct composite_context *c = resolve_name_host_send(mem_ctx, NULL, NULL, name);
+ return resolve_name_host_recv(c, mem_ctx, addrs);
}
+bool resolve_context_add_host_method(struct resolve_context *ctx)
+{
+ return resolve_context_add_method(ctx, resolve_name_host_send, resolve_name_host_recv,
+ NULL);
+}