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

Reply via email to