The branch, master has been updated via 13ac91d nss_wins: Add a stackframe to lookup_byname_backend() via 10f5fa8 s3: Make use of name_resolve_bcast in nmblookup via 2d90a89 s3: Make name_resolve_bcast do parallel lookups to all interfaces via fbe7b47 s3: Add name_queries_send/recv from 114fbc3 s3: Fix a valgrind error
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 13ac91d9a1e695aa5b4147bc13c728eb1cb562e8 Author: Volker Lendecke <v...@samba.org> Date: Mon May 16 14:48:39 2011 +0200 nss_wins: Add a stackframe to lookup_byname_backend() Autobuild-User: Volker Lendecke <vlen...@samba.org> Autobuild-Date: Sun Jun 5 15:17:42 CEST 2011 on sn-devel-104 commit 10f5fa8a1e2272cf2388277b17e00082b2973216 Author: Volker Lendecke <v...@samba.org> Date: Mon May 2 23:39:09 2011 +0200 s3: Make use of name_resolve_bcast in nmblookup commit 2d90a8994245b3611a508fed4ddcf0bd4ad978d9 Author: Volker Lendecke <v...@samba.org> Date: Mon Apr 25 18:47:42 2011 +0200 s3: Make name_resolve_bcast do parallel lookups to all interfaces commit fbe7b47c343c6f3aaf11acd5b16e499388baaa23 Author: Volker Lendecke <v...@samba.org> Date: Mon Apr 25 18:30:35 2011 +0200 s3: Add name_queries_send/recv ----------------------------------------------------------------------- Summary of changes: nsswitch/wins.c | 10 +- source3/libsmb/namequery.c | 271 ++++++++++++++++++++++++++++++++++++++++---- source3/utils/nmblookup.c | 24 +---- 3 files changed, 260 insertions(+), 45 deletions(-) Changeset truncated at 500 lines: diff --git a/nsswitch/wins.c b/nsswitch/wins.c index 1bfdcd9..5c9ad2f 100644 --- a/nsswitch/wins.c +++ b/nsswitch/wins.c @@ -59,6 +59,7 @@ static void nss_wins_init(void) static struct in_addr *lookup_byname_backend(const char *name, int *count) { + TALLOC_CTX *frame = talloc_stackframe(); struct ip_service *address = NULL; struct in_addr *ret = NULL; int j; @@ -73,16 +74,19 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) { if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) { free( address ); + TALLOC_FREE(frame); return NULL; } if (address[0].ss.ss_family != AF_INET) { free(address); free(ret); + TALLOC_FREE(frame); return NULL; } *ret = ((struct sockaddr_in *)(void *)&address[0].ss) ->sin_addr; free( address ); + TALLOC_FREE(frame); return ret; } @@ -98,17 +102,17 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) } in_addr_to_sockaddr_storage(&ss, *bcast); status = name_query(name, 0x00, True, True, &ss, - NULL, &pss, count, NULL); + talloc_tos(), &pss, count, NULL); if (NT_STATUS_IS_OK(status) && (*count > 0)) { if ((ret = SMB_MALLOC_P(struct in_addr)) == NULL) { + TALLOC_FREE(frame); return NULL; } *ret = ((struct sockaddr_in *)pss)->sin_addr; - TALLOC_FREE(pss); break; } } - + TALLOC_FREE(frame); return ret; } diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 1cd5eb7..7bb8caf 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1507,6 +1507,237 @@ static bool convert_ss2service(struct ip_service **return_iplist, return true; } +struct name_queries_state { + struct tevent_context *ev; + const char *name; + int name_type; + bool bcast; + bool recurse; + const struct sockaddr_storage *addrs; + int num_addrs; + int wait_msec; + int timeout_msec; + + struct tevent_req **subreqs; + int num_received; + int num_sent; + + int received_index; + struct sockaddr_storage *result_addrs; + int num_result_addrs; + uint8_t flags; +}; + +static void name_queries_done(struct tevent_req *subreq); +static void name_queries_next(struct tevent_req *subreq); + +/* + * Send a name query to multiple destinations with a wait time in between + */ + +static struct tevent_req *name_queries_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *name, int name_type, + bool bcast, bool recurse, + const struct sockaddr_storage *addrs, + int num_addrs, int wait_msec, int timeout_msec) +{ + struct tevent_req *req, *subreq; + struct name_queries_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct name_queries_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->name = name; + state->name_type = name_type; + state->bcast = bcast; + state->recurse = recurse; + state->addrs = addrs; + state->num_addrs = num_addrs; + state->wait_msec = wait_msec; + state->timeout_msec = timeout_msec; + + state->subreqs = talloc_zero_array( + state, struct tevent_req *, num_addrs); + if (tevent_req_nomem(state->subreqs, req)) { + return tevent_req_post(req, ev); + } + state->num_sent = 0; + + subreq = name_query_send( + state->subreqs, state->ev, name, name_type, bcast, recurse, + &state->addrs[state->num_sent]); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + if (!tevent_req_set_endtime( + subreq, state->ev, + timeval_current_ofs(0, state->timeout_msec * 1000))) { + tevent_req_nomem(NULL, req); + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, name_queries_done, req); + + state->subreqs[state->num_sent] = subreq; + state->num_sent += 1; + + if (state->num_sent < state->num_addrs) { + subreq = tevent_wakeup_send( + state, state->ev, + timeval_current_ofs(0, state->wait_msec * 1000)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, name_queries_next, req); + } + return req; +} + +static void name_queries_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct name_queries_state *state = tevent_req_data( + req, struct name_queries_state); + int i; + NTSTATUS status; + + status = name_query_recv(subreq, state, &state->result_addrs, + &state->num_result_addrs, &state->flags); + + for (i=0; i<state->num_sent; i++) { + if (state->subreqs[i] == subreq) { + break; + } + } + if (i == state->num_sent) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + TALLOC_FREE(state->subreqs[i]); + + state->num_received += 1; + + if (!NT_STATUS_IS_OK(status)) { + + if (state->num_received >= state->num_addrs) { + tevent_req_nterror(req, status); + return; + } + /* + * Still outstanding requests, just wait + */ + return; + } + state->received_index = i; + tevent_req_done(req); +} + +static void name_queries_next(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct name_queries_state *state = tevent_req_data( + req, struct name_queries_state); + + if (!tevent_wakeup_recv(subreq)) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + subreq = name_query_send( + state->subreqs, state->ev, + state->name, state->name_type, state->bcast, state->recurse, + &state->addrs[state->num_sent]); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, name_queries_done, req); + if (!tevent_req_set_endtime( + subreq, state->ev, + timeval_current_ofs(0, state->timeout_msec * 1000))) { + tevent_req_nomem(NULL, req); + return; + } + state->subreqs[state->num_sent] = subreq; + state->num_sent += 1; + + if (state->num_sent < state->num_addrs) { + subreq = tevent_wakeup_send( + state, state->ev, + timeval_current_ofs(0, state->wait_msec * 1000)); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, name_queries_next, req); + } +} + +static NTSTATUS name_queries_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct sockaddr_storage **result_addrs, + int *num_result_addrs, uint8_t *flags, + int *received_index) +{ + struct name_queries_state *state = tevent_req_data( + req, struct name_queries_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + + if (result_addrs != NULL) { + *result_addrs = talloc_move(mem_ctx, &state->result_addrs); + } + if (num_result_addrs != NULL) { + *num_result_addrs = state->num_result_addrs; + } + if (flags != NULL) { + *flags = state->flags; + } + if (received_index != NULL) { + *received_index = state->received_index; + } + return NT_STATUS_OK; +} + +static NTSTATUS name_queries(const char *name, int name_type, + bool bcast, bool recurse, + const struct sockaddr_storage *addrs, + int num_addrs, int wait_msec, int timeout_msec, + TALLOC_CTX *mem_ctx, + struct sockaddr_storage **result_addrs, + int *num_result_addrs, uint8_t *flags, + int *received_index) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = event_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = name_queries_send(frame, ev, name, name_type, bcast, + recurse, addrs, num_addrs, wait_msec, + timeout_msec); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = name_queries_recv(req, mem_ctx, result_addrs, + num_result_addrs, flags, received_index); + fail: + TALLOC_FREE(frame); + return status; +} + /******************************************************** Resolve via "bcast" method. *********************************************************/ @@ -1517,8 +1748,8 @@ NTSTATUS name_resolve_bcast(const char *name, struct sockaddr_storage **return_iplist, int *return_count) { - int i; - int num_interfaces = iface_count(); + struct sockaddr_storage *bcast_addrs; + int i, num_addrs, num_bcast_addrs; struct sockaddr_storage *ss_list; NTSTATUS status = NT_STATUS_NOT_FOUND; @@ -1528,9 +1759,6 @@ NTSTATUS name_resolve_bcast(const char *name, return NT_STATUS_INVALID_PARAMETER; } - *return_iplist = NULL; - *return_count = 0; - /* * "bcast" means do a broadcast lookup on all the local interfaces. */ @@ -1538,32 +1766,33 @@ NTSTATUS name_resolve_bcast(const char *name, DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup " "for name %s<0x%x>\n", name, name_type)); + num_addrs = iface_count(); + bcast_addrs = talloc_array(talloc_tos(), struct sockaddr_storage, + num_addrs); + if (bcast_addrs == NULL) { + return NT_STATUS_NO_MEMORY; + } + /* * Lookup the name on all the interfaces, return on * the first successful match. */ - for( i = num_interfaces-1; i >= 0; i--) { + num_bcast_addrs = 0; + + for (i=0; i<num_addrs; i++) { const struct sockaddr_storage *pss = iface_n_bcast(i); - /* Done this way to fix compiler error on IRIX 5.x */ - if (!pss) { + if (pss->ss_family != AF_INET) { continue; } - status = name_query(name, name_type, true, true, pss, - talloc_tos(), &ss_list, return_count, - NULL); - if (NT_STATUS_IS_OK(status)) { - goto success; - } + bcast_addrs[num_bcast_addrs] = *pss; + num_bcast_addrs += 1; } - /* failed - no response */ - - return status; - -success: - *return_iplist = ss_list; - return status; + return name_queries(name, name_type, true, true, + bcast_addrs, num_bcast_addrs, 0, 1000, + mem_ctx, return_iplist, return_count, + NULL, NULL); } /******************************************************** diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c index f854540..73db278 100644 --- a/source3/utils/nmblookup.c +++ b/source3/utils/nmblookup.c @@ -168,27 +168,9 @@ static bool query_one(const char *lookup, unsigned int lookup_type) &bcast_addr, talloc_tos(), &ip_list, &count, &flags); } else { - const struct in_addr *bcast; - for (j=iface_count() - 1; - !ip_list && j >= 0; - j--) { - char addr[INET6_ADDRSTRLEN]; - struct sockaddr_storage bcast_ss; - - bcast = iface_n_bcast_v4(j); - if (!bcast) { - continue; - } - in_addr_to_sockaddr_storage(&bcast_ss, *bcast); - print_sockaddr(addr, sizeof(addr), &bcast_ss); - d_printf("querying %s on %s\n", - lookup, addr); - status = name_query(lookup,lookup_type, - use_bcast, - use_bcast?True:recursion_desired, - &bcast_ss, talloc_tos(), - &ip_list, &count, &flags); - } + status = name_resolve_bcast( + lookup, lookup_type, + talloc_tos(), &ip_list, &count); } if (!NT_STATUS_IS_OK(status)) { -- Samba Shared Repository