The branch, master has been updated
       via  c118bcf s3: Use resolve_wins_send/recv in resolve_wins
       via  0dfcf3e s3: Add resolve_wins_send/recv
       via  396b646 s3: Add wins_server_tag_ips()
       via  12c3c35 s3: Add query_wins_list_send/recv
       via  f0994c7 s3: Fix IO_TIMEOUT handling for wins queries
       via  ebf04d7 s3: Remove "struct ip_service" from resolve_wins
       via  eb16915 nsswitch: Remove some refs to the global winbindd_fd
      from  d566146 s3-passdb: Implement new pdb trust calls for the default 
backend

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c118bcf7556929aadf853a3e0bb7748210126dd2
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Jun 3 16:11:17 2011 +0200

    s3: Use resolve_wins_send/recv in resolve_wins
    
    Autobuild-User: Volker Lendecke <vlen...@samba.org>
    Autobuild-Date: Sun Jun 12 18:19:41 CEST 2011 on sn-devel-104

commit 0dfcf3ef78bb16d79644ee08f58d519e74ff0f0a
Author: Volker Lendecke <v...@samba.org>
Date:   Thu Jun 2 14:12:06 2011 +0200

    s3: Add resolve_wins_send/recv

commit 396b646123c1aef81c644ae744e65c71b30067d0
Author: Volker Lendecke <v...@samba.org>
Date:   Sun Jun 12 14:07:22 2011 +0200

    s3: Add wins_server_tag_ips()
    
    For a given tag, return the list of all wins servers

commit 12c3c355966ba7c2da101219ae993fd0ef633026
Author: Volker Lendecke <v...@samba.org>
Date:   Sat May 14 18:24:03 2011 +0200

    s3: Add query_wins_list_send/recv

commit f0994c749505f11ea115f9e1ae7de52cf25412d0
Author: Volker Lendecke <v...@samba.org>
Date:   Sun Jun 12 15:44:19 2011 +0200

    s3: Fix IO_TIMEOUT handling for wins queries

commit ebf04d79abdf0a15248a266162c8ec8906ce3c5f
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Jun 3 15:49:55 2011 +0200

    s3: Remove "struct ip_service" from resolve_wins

commit eb16915e283879aaf0797896fc9bd96b095ff550
Author: Volker Lendecke <v...@samba.org>
Date:   Sun Jun 5 16:39:36 2011 +0200

    nsswitch: Remove some refs to the global winbindd_fd

-----------------------------------------------------------------------

Summary of changes:
 nsswitch/wb_common.c             |   18 +-
 nsswitch/wins.c                  |   15 +-
 source3/include/proto.h          |   12 +-
 source3/lib/wins_srv.c           |   42 ++++
 source3/libsmb/namequery.c       |  403 ++++++++++++++++++++++++++++++--------
 source3/winbindd/winbindd_wins.c |   18 +--
 6 files changed, 394 insertions(+), 114 deletions(-)


Changeset truncated at 500 lines:

diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c
index dcfc8a5..80c729a 100644
--- a/nsswitch/wb_common.c
+++ b/nsswitch/wb_common.c
@@ -369,13 +369,14 @@ static int winbind_open_pipe_sock(int recursing, int 
need_priv)
 static int winbind_write_sock(void *buffer, int count, int recursing,
                              int need_priv)
 {
-       int result, nwritten;
+       int fd, result, nwritten;
 
        /* Open connection to winbind daemon */
 
  restart:
 
-       if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
+       fd = winbind_open_pipe_sock(recursing, need_priv);
+       if (fd == -1) {
                errno = ENOENT;
                return -1;
        }
@@ -391,7 +392,7 @@ static int winbind_write_sock(void *buffer, int count, int 
recursing,
                /* Catch pipe close on other end by checking if a read()
                   call would not block by calling poll(). */
 
-               pfd.fd = winbindd_fd;
+               pfd.fd = fd;
                pfd.events = POLLIN|POLLHUP;
 
                ret = poll(&pfd, 1, 0);
@@ -412,8 +413,7 @@ static int winbind_write_sock(void *buffer, int count, int 
recursing,
 
                /* Do the write */
 
-               result = write(winbindd_fd,
-                              (char *)buffer + nwritten,
+               result = write(fd, (char *)buffer + nwritten,
                               count - nwritten);
 
                if ((result == -1) || (result == 0)) {
@@ -434,10 +434,12 @@ static int winbind_write_sock(void *buffer, int count, 
int recursing,
 
 static int winbind_read_sock(void *buffer, int count)
 {
+       int fd;
        int nread = 0;
        int total_time = 0;
 
-       if (winbindd_fd == -1) {
+       fd = winbind_open_pipe_sock(false, false);
+       if (fd == -1) {
                return -1;
        }
 
@@ -449,7 +451,7 @@ static int winbind_read_sock(void *buffer, int count)
                /* Catch pipe close on other end by checking if a read()
                   call would not block by calling poll(). */
 
-               pfd.fd = winbindd_fd;
+               pfd.fd = fd;
                pfd.events = POLLIN|POLLHUP;
 
                /* Wait for 5 seconds for a reply. May need to parameterise 
this... */
@@ -475,7 +477,7 @@ static int winbind_read_sock(void *buffer, int count)
 
                        /* Do the Read */
 
-                       int result = read(winbindd_fd, (char *)buffer + nread,
+                       int result = read(fd, (char *)buffer + nread,
                              count - nread);
 
                        if ((result == -1) || (result == 0)) {
diff --git a/nsswitch/wins.c b/nsswitch/wins.c
index 5c9ad2f..d63968b 100644
--- a/nsswitch/wins.c
+++ b/nsswitch/wins.c
@@ -60,8 +60,9 @@ 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 sockaddr_storage *address = NULL;
        struct in_addr *ret = NULL;
+       NTSTATUS status;
        int j;
 
        if (!initialised) {
@@ -71,21 +72,20 @@ static struct in_addr *lookup_byname_backend(const char 
*name, int *count)
        *count = 0;
 
        /* always try with wins first */
-       if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) {
+       status = resolve_wins(name, 0x00, talloc_tos(),
+                             &address, count);
+       if (NT_STATUS_IS_OK(status)) {
                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);
+               if (address[0].ss_family != AF_INET) {
                        free(ret);
                        TALLOC_FREE(frame);
                        return NULL;
                }
-               *ret = ((struct sockaddr_in *)(void *)&address[0].ss)
+               *ret = ((struct sockaddr_in *)(void *)address)
                        ->sin_addr;
-               free( address );
                TALLOC_FREE(frame);
                return ret;
        }
@@ -95,7 +95,6 @@ static struct in_addr *lookup_byname_backend(const char 
*name, int *count)
                const struct in_addr *bcast = iface_n_bcast_v4(j);
                struct sockaddr_storage ss;
                struct sockaddr_storage *pss;
-               NTSTATUS status;
 
                if (!bcast) {
                        continue;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 1cde4be..ad8ae99 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -913,6 +913,8 @@ unsigned wins_srv_count(void);
 char **wins_srv_tags(void);
 void wins_srv_tags_free(char **list);
 struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip);
+bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx,
+                        struct in_addr **pservers, int *pnum_servers);
 unsigned wins_srv_count_tag(const char *tag);
 
 /* The following definitions come from libsmb/clispnego.c  */
@@ -1050,9 +1052,17 @@ 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,
-               struct ip_service **return_iplist,
+               TALLOC_CTX *mem_ctx,
+               struct sockaddr_storage **return_iplist,
                int *return_count);
 NTSTATUS internal_resolve_name(const char *name,
                                int name_type,
diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c
index 6676f02..f9e8f3b 100644
--- a/source3/lib/wins_srv.c
+++ b/source3/lib/wins_srv.c
@@ -328,6 +328,48 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct 
in_addr src_ip)
        return t_ip.ip;
 }
 
+bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx,
+                        struct in_addr **pservers, int *pnum_servers)
+{
+       const char **list;
+       int i, num_servers;
+       struct in_addr *servers;
+
+       list = lp_wins_server_list();
+       if ((list == NULL) || (list[0] == NULL)) {
+               return false;
+       }
+
+       num_servers = 0;
+
+       for (i=0; list[i] != NULL; i++) {
+               struct tagged_ip t_ip;
+               parse_ip(&t_ip, list[i]);
+               if (strcmp(tag, t_ip.tag) == 0) {
+                       num_servers += 1;
+               }
+       }
+
+       servers = talloc_array(mem_ctx, struct in_addr, num_servers);
+       if (servers == NULL) {
+               return false;
+       }
+
+       num_servers = 0;
+
+       for (i=0; list[i] != NULL; i++) {
+               struct tagged_ip t_ip;
+               parse_ip(&t_ip, list[i]);
+               if (strcmp(tag, t_ip.tag) == 0) {
+                       servers[num_servers] = t_ip.ip;
+                       num_servers += 1;
+               }
+       }
+       *pnum_servers = num_servers;
+       *pservers = servers;
+       return true;
+}
+
 
 /*
   return a count of the number of IPs for a particular tag, including
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 511eba4..dc062fb 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -208,6 +208,15 @@ static void set_socket_addr_v4(struct sockaddr_storage 
*addr)
        }
 }
 
+static struct in_addr my_socket_addr_v4(void)
+{
+       struct sockaddr_storage my_addr;
+       struct sockaddr_in *in_addr = (struct sockaddr_in *)((char *)&my_addr);
+
+       set_socket_addr_v4(&my_addr);
+       return in_addr->sin_addr;
+}
+
 /****************************************************************************
  Generate a random trn_id.
 ****************************************************************************/
@@ -1423,9 +1432,18 @@ NTSTATUS name_query_recv(struct tevent_req *req, 
TALLOC_CTX *mem_ctx,
                req, struct name_query_state);
        NTSTATUS status;
 
-       if (tevent_req_is_nterror(req, &status)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               return status;
+       if (tevent_req_is_nterror(req, &status)) {
+               if (state->bcast &&
+                   NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       /*
+                        * In the broadcast case we collect replies until the
+                        * timeout.
+                        */
+                       status = NT_STATUS_OK;
+               }
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
        }
        if (state->num_addrs == 0) {
                return NT_STATUS_NOT_FOUND;
@@ -1793,45 +1811,175 @@ NTSTATUS name_resolve_bcast(const char *name,
                            NULL, NULL);
 }
 
-/********************************************************
- Resolve via "wins" method.
-*********************************************************/
+struct query_wins_list_state {
+       struct tevent_context *ev;
+       const char *name;
+       uint8_t name_type;
+       struct in_addr *servers;
+       uint32_t num_servers;
+       struct sockaddr_storage server;
+       uint32_t num_sent;
 
-NTSTATUS resolve_wins(const char *name,
-               int name_type,
-               struct ip_service **return_iplist,
-               int *return_count)
+       struct sockaddr_storage *addrs;
+       int num_addrs;
+       uint8_t flags;
+};
+
+static void query_wins_list_done(struct tevent_req *subreq);
+
+/*
+ * Query a list of (replicating) wins servers in sequence, call them
+ * dead if they don't reply
+ */
+
+static struct tevent_req *query_wins_list_send(
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct in_addr src_ip, const char *name, uint8_t name_type,
+       struct in_addr *servers, int num_servers)
 {
-       int t, i;
-       char **wins_tags;
-       struct sockaddr_storage src_ss, *ss_list = NULL;
-       struct in_addr src_ip;
+       struct tevent_req *req, *subreq;
+       struct query_wins_list_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct query_wins_list_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->name = name;
+       state->name_type = name_type;
+       state->servers = servers;
+       state->num_servers = num_servers;
+
+       if (state->num_servers == 0) {
+               tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
+               return tevent_req_post(req, ev);
+       }
+
+       in_addr_to_sockaddr_storage(
+               &state->server, state->servers[state->num_sent]);
+
+       subreq = name_query_send(state, state->ev,
+                                state->name, state->name_type,
+                                false, true, &state->server);
+       state->num_sent += 1;
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       if (!tevent_req_set_endtime(subreq, state->ev,
+                                   timeval_current_ofs(2, 0))) {
+               tevent_req_nomem(NULL, req);
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, query_wins_list_done, req);
+       return req;
+}
+
+static void query_wins_list_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct query_wins_list_state *state = tevent_req_data(
+               req, struct query_wins_list_state);
        NTSTATUS status;
 
-       if (lp_disable_netbios()) {
-               DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n",
-                                       name, name_type));
-               return NT_STATUS_INVALID_PARAMETER;
+       status = name_query_recv(subreq, state,
+                                &state->addrs, &state->num_addrs,
+                                &state->flags);
+       TALLOC_FREE(subreq);
+       if (NT_STATUS_IS_OK(status)) {
+               tevent_req_done(req);
+               return;
        }
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+       wins_srv_died(state->servers[state->num_sent-1],
+                     my_socket_addr_v4());
 
-       *return_iplist = NULL;
-       *return_count = 0;
+       if (state->num_sent == state->num_servers) {
+               tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
+               return;
+       }
 
-       DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n",
-                               name, name_type));
+       in_addr_to_sockaddr_storage(
+               &state->server, state->servers[state->num_sent]);
 
-       if (wins_srv_count() < 1) {
-               DEBUG(3,("resolve_wins: WINS server resolution selected "
-                       "and no WINS servers listed.\n"));
-               return NT_STATUS_INVALID_PARAMETER;
+       subreq = name_query_send(state, state->ev,
+                                state->name, state->name_type,
+                                false, true, &state->server);
+       state->num_sent += 1;
+       if (tevent_req_nomem(subreq, req)) {
+               return;
        }
+       if (!tevent_req_set_endtime(subreq, state->ev,
+                                   timeval_current_ofs(2, 0))) {
+               tevent_req_nomem(NULL, req);
+               return;
+       }
+       tevent_req_set_callback(subreq, query_wins_list_done, req);
+}
 
-       /* we try a lookup on each of the WINS tags in turn */
-       wins_tags = wins_srv_tags();
+static NTSTATUS query_wins_list_recv(struct tevent_req *req,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct sockaddr_storage **addrs,
+                                    int *num_addrs,
+                                    uint8_t *flags)
+{
+       struct query_wins_list_state *state = tevent_req_data(
+               req, struct query_wins_list_state);
+       NTSTATUS status;
 
-       if (!wins_tags) {
-               /* huh? no tags?? give up in disgust */
-               return NT_STATUS_INVALID_PARAMETER;
+       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;
+}
+
+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 */
@@ -1846,80 +1994,164 @@ NTSTATUS resolve_wins(const char *name,
                DEBUG(3,("resolve_wins: cannot receive WINS replies "
                        "on IPv6 address %s\n",
                        addr));
-               wins_srv_tags_free(wins_tags);
-               return NT_STATUS_INVALID_PARAMETER;
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto fail;
        }
 
-       src_ip = ((struct sockaddr_in *)&src_ss)->sin_addr;
+       src_ip = ((const struct sockaddr_in *)(void *)&src_ss)->sin_addr;
 
-       /* in the worst case we will try every wins server with every
-          tag! */
-       for (t=0; wins_tags && wins_tags[t]; t++) {
-               int srv_count = wins_srv_count_tag(wins_tags[t]);
-               for (i=0; i<srv_count; i++) {
-                       struct sockaddr_storage wins_ss;
-                       struct in_addr wins_ip;
+       wins_tags = wins_srv_tags();
+       if (wins_tags == NULL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto fail;
+       }
 
-                       wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
+       num_wins_tags = 0;
+       while (wins_tags[num_wins_tags] != NULL) {
+               num_wins_tags += 1;
+       }
+
+       for (i=0; i<num_wins_tags; i++) {
+               int num_servers, num_alive;
+               struct in_addr *servers, *alive;
+               int j;
+
+               if (!wins_server_tag_ips(wins_tags[i], talloc_tos(),
+                                        &servers, &num_servers)) {
+                       DEBUG(10, ("wins_server_tag_ips failed for tag %s\n",
+                                  wins_tags[i]));
+                       continue;
+               }
+
+               alive = talloc_array(state, struct in_addr, num_servers);
+               if (tevent_req_nomem(alive, req)) {
+                       goto fail;


-- 
Samba Shared Repository

Reply via email to