From 0dfcf3ef78bb16d79644ee08f58d519e74ff0f0a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 2 Jun 2011 14:12:06 +0200 Subject: s3: Add resolve_wins_send/recv --- source3/include/proto.h | 7 ++ source3/libsmb/namequery.c | 177 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 815104881d..ad8ae994ff 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1052,6 +1052,13 @@ NTSTATUS name_resolve_bcast(const char *name, TALLOC_CTX *mem_ctx, struct sockaddr_storage **return_iplist, int *return_count); +struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + int name_type); +NTSTATUS resolve_wins_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct sockaddr_storage **addrs, + int *num_addrs, uint8_t *flags); NTSTATUS resolve_wins(const char *name, int name_type, TALLOC_CTX *mem_ctx, diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index ecb984d2aa..28fc33e32b 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1946,6 +1946,183 @@ static NTSTATUS query_wins_list_recv(struct tevent_req *req, return NT_STATUS_OK; } +struct resolve_wins_state { + int num_sent; + int num_received; + + struct sockaddr_storage *addrs; + int num_addrs; + uint8_t flags; +}; + +static void resolve_wins_done(struct tevent_req *subreq); + +struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const char *name, + int name_type) +{ + struct tevent_req *req, *subreq; + struct resolve_wins_state *state; + char **wins_tags = NULL; + struct sockaddr_storage src_ss; + struct in_addr src_ip; + int i, num_wins_tags; + + req = tevent_req_create(mem_ctx, &state, + struct resolve_wins_state); + if (req == NULL) { + return NULL; + } + + if (wins_srv_count() < 1) { + DEBUG(3,("resolve_wins: WINS server resolution selected " + "and no WINS servers listed.\n")); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; + } + + /* the address we will be sending from */ + if (!interpret_string_addr(&src_ss, lp_socket_address(), + AI_NUMERICHOST|AI_PASSIVE)) { + zero_sockaddr(&src_ss); + } + + if (src_ss.ss_family != AF_INET) { + char addr[INET6_ADDRSTRLEN]; + print_sockaddr(addr, sizeof(addr), &src_ss); + DEBUG(3,("resolve_wins: cannot receive WINS replies " + "on IPv6 address %s\n", + addr)); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; + } + + src_ip = ((const struct sockaddr_in *)(void *)&src_ss)->sin_addr; + + wins_tags = wins_srv_tags(); + if (wins_tags == NULL) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto fail; + } + + num_wins_tags = 0; + while (wins_tags[num_wins_tags] != NULL) { + num_wins_tags += 1; + } + + for (i=0; inum_sent += 1; + } + + if (state->num_sent == 0) { + tevent_req_nterror(req, NT_STATUS_NOT_FOUND); + goto fail; + } + + wins_srv_tags_free(wins_tags); + return req; +fail: + wins_srv_tags_free(wins_tags); + return tevent_req_post(req, ev); +} + +static void resolve_wins_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct resolve_wins_state *state = tevent_req_data( + req, struct resolve_wins_state); + NTSTATUS status; + + status = query_wins_list_recv(subreq, state, &state->addrs, + &state->num_addrs, &state->flags); + if (NT_STATUS_IS_OK(status)) { + tevent_req_done(req); + return; + } + + state->num_received += 1; + + if (state->num_received < state->num_sent) { + /* + * Wait for the others + */ + return; + } + tevent_req_nterror(req, status); +} + +NTSTATUS resolve_wins_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct sockaddr_storage **addrs, + int *num_addrs, uint8_t *flags) +{ + struct resolve_wins_state *state = tevent_req_data( + req, struct resolve_wins_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + if (addrs != NULL) { + *addrs = talloc_move(mem_ctx, &state->addrs); + } + if (num_addrs != NULL) { + *num_addrs = state->num_addrs; + } + if (flags != NULL) { + *flags = state->flags; + } + return NT_STATUS_OK; +} + /******************************************************** Resolve via "wins" method. *********************************************************/ -- cgit