The branch, master has been updated
       via  d06fb8e0.. s3: List trusted domains from wcache when domain is 
offline.
       via  133638c... s3: Make winbindd_cache.c aware of domain offline to 
avoid unnecessary backend query.
       via  36493bf... s3: Fix infinite loop in NCACN_IP_TCP asa there is no 
timeout. Assume lsa_pipe_tcp is ok but network is down, then send request is 
ok, but select() on writeable fds loops forever since there is no response.
      from  da41f23... s3 net: Fix up a share type translation and translate 
some more strings

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


- Log -----------------------------------------------------------------
commit d06fb8e02706559e91c6d185427409bb093bb896
Author: Bo Yang <[email protected]>
Date:   Wed Jan 6 19:13:59 2010 +0800

    s3: List trusted domains from wcache when domain is offline.
    
    Signed-off-by: Bo Yang <[email protected]>

commit 133638c8aea7280d01b5a23150428977e9ff0e11
Author: Bo Yang <[email protected]>
Date:   Wed Jan 6 15:05:20 2010 +0800

    s3: Make winbindd_cache.c aware of domain offline to avoid unnecessary 
backend query.
    
    Signed-off-by: Bo Yang <[email protected]>

commit 36493bf2f6634b84c57107bcb86bcbf3e82e80fc
Author: Bo Yang <[email protected]>
Date:   Wed Jan 6 12:13:35 2010 +0800

    s3: Fix infinite loop in NCACN_IP_TCP asa there is no timeout. Assume 
lsa_pipe_tcp is ok but network is down, then send request is ok, but select() 
on writeable fds loops forever since there is no response.
    
    Signed-off-by: Bo Yang <[email protected]>

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

Summary of changes:
 source3/include/proto.h                 |    5 +
 source3/rpc_client/cli_pipe.c           |   26 ++-
 source3/rpc_client/ndr.c                |   15 ++
 source3/rpc_client/rpc_transport_np.c   |   12 +
 source3/rpc_client/rpc_transport_smbd.c |   10 +
 source3/rpc_client/rpc_transport_sock.c |   53 +++++
 source3/winbindd/winbindd_cache.c       |  380 ++++++++++++++++++++++++++++++-
 source3/winbindd/winbindd_cm.c          |    3 +-
 source3/winbindd/winbindd_rpc.c         |   14 +-
 9 files changed, 501 insertions(+), 17 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index b3921c4..d956ede 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5396,6 +5396,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, 
struct cli_state *cli,
                               const struct ndr_syntax_id *abstract_syntax,
                               struct rpc_cli_transport **presult);
 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p);
+void rpccli_close_np_fd(struct rpc_pipe_client *p);
 
 /* The following definitions come from rpc_client/rpc_transport_smbd.c  */
 
@@ -5426,11 +5427,15 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
                                 struct rpc_cli_smbd_conn *conn,
                                 const struct ndr_syntax_id *abstract_syntax,
                                 struct rpc_cli_transport **presult);
+struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p);
 
 /* The following definitions come from rpc_client/rpc_transport_sock.c  */
 
 NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int fd,
                                 struct rpc_cli_transport **presult);
+int rpccli_set_sock_timeout(struct rpc_pipe_client *rpccli, int timeout);
+void rpccli_close_sock_fd(struct rpc_pipe_client *rpccli);
+bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *rpccli);
 
 /* The following definitions come from rpc_client/cli_samr.c  */
 
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 9653166..48e2f9e 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -3035,12 +3035,30 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
                                unsigned int timeout)
 {
-       struct cli_state *cli = rpc_pipe_np_smb_conn(rpc_cli);
+       struct cli_state *cli;
 
-       if (cli == NULL) {
-               return 0;
+       if (rpc_cli->transport->transport == NCACN_NP) {
+               cli = rpc_pipe_np_smb_conn(rpc_cli);
+               if (cli == NULL) {
+                       return 0;
+               }
+               return cli_set_timeout(cli, timeout);
+       }
+
+       if (rpc_cli->transport->transport == NCACN_IP_TCP ||
+           rpc_cli->transport->transport == NCALRPC) {
+               return rpccli_set_sock_timeout(rpc_cli, timeout);
        }
-       return cli_set_timeout(cli, timeout);
+
+       if (rpc_cli->transport->transport == NCACN_INTERNAL) {
+               cli = rpc_pipe_smbd_smb_conn(rpc_cli);
+               if (!cli) {
+                       return 0;
+               }
+               return cli_set_timeout(cli, timeout);
+       }
+
+       return 0;
 }
 
 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
diff --git a/source3/rpc_client/ndr.c b/source3/rpc_client/ndr.c
index 6433a7d..4e8634d 100644
--- a/source3/rpc_client/ndr.c
+++ b/source3/rpc_client/ndr.c
@@ -182,6 +182,21 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
        }
 
        status = cli_do_rpc_ndr_recv(req, mem_ctx);
+
+       /*
+        * NT_STATUS_IO_TIMEOUT indicates network problem,
+        * tear the connection apart.
+        */
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+               if (cli->transport->transport == NCACN_IP_TCP ||
+                   cli->transport->transport == NCALRPC) {
+                       rpccli_close_sock_fd(cli);
+               }
+
+               if (cli->transport->transport == NCACN_NP) {
+                       rpccli_close_np_fd(cli);
+               }
+       }
  fail:
        TALLOC_FREE(frame);
        return status;
diff --git a/source3/rpc_client/rpc_transport_np.c 
b/source3/rpc_client/rpc_transport_np.c
index de748d9..9f8872c 100644
--- a/source3/rpc_client/rpc_transport_np.c
+++ b/source3/rpc_client/rpc_transport_np.c
@@ -402,3 +402,15 @@ struct cli_state *rpc_pipe_np_smb_conn(struct 
rpc_pipe_client *p)
        }
        return state->cli;
 }
+
+void rpccli_close_np_fd(struct rpc_pipe_client *p)
+{
+       struct cli_state *cli = rpc_pipe_np_smb_conn(p);
+       if (cli) {
+               if (cli->fd != -1) {
+                       close(cli->fd);
+                       cli->fd = -1;
+               }
+       }
+       return;
+}
diff --git a/source3/rpc_client/rpc_transport_smbd.c 
b/source3/rpc_client/rpc_transport_smbd.c
index 171048a..929e553 100644
--- a/source3/rpc_client/rpc_transport_smbd.c
+++ b/source3/rpc_client/rpc_transport_smbd.c
@@ -682,3 +682,13 @@ NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
        TALLOC_FREE(frame);
        return status;
 }
+
+struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p)
+{
+       struct rpc_transport_smbd_state *state = 
talloc_get_type(p->transport->priv,
+               struct rpc_transport_smbd_state);
+       if (!state || !state->conn) {
+               return NULL;
+       }
+       return state->conn->cli;
+}
diff --git a/source3/rpc_client/rpc_transport_sock.c 
b/source3/rpc_client/rpc_transport_sock.c
index 4ab6500..df060e6 100644
--- a/source3/rpc_client/rpc_transport_sock.c
+++ b/source3/rpc_client/rpc_transport_sock.c
@@ -24,6 +24,7 @@
 
 struct rpc_transport_sock_state {
        int fd;
+       int timeout;
 };
 
 static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state 
*s)
@@ -51,6 +52,7 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX 
*mem_ctx,
                priv, struct rpc_transport_sock_state);
        struct tevent_req *req, *subreq;
        struct rpc_sock_read_state *state;
+       struct timeval endtime;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_sock_read_state);
        if (req == NULL) {
@@ -61,10 +63,16 @@ static struct tevent_req *rpc_sock_read_send(TALLOC_CTX 
*mem_ctx,
                return tevent_req_post(req, ev);
        }
        state->transp = sock_transp;
+       endtime = timeval_current_ofs(0, sock_transp->timeout * 1000);
        subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0);
        if (subreq == NULL) {
                goto fail;
        }
+
+       if (!tevent_req_set_endtime(subreq, ev, endtime)) {
+               goto fail;
+       }
+
        tevent_req_set_callback(subreq, rpc_sock_read_done, req);
        return req;
  fail:
@@ -121,6 +129,7 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX 
*mem_ctx,
                priv, struct rpc_transport_sock_state);
        struct tevent_req *req, *subreq;
        struct rpc_sock_write_state *state;
+       struct timeval endtime;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_sock_write_state);
        if (req == NULL) {
@@ -131,10 +140,16 @@ static struct tevent_req *rpc_sock_write_send(TALLOC_CTX 
*mem_ctx,
                return tevent_req_post(req, ev);
        }
        state->transp = sock_transp;
+       endtime = timeval_current_ofs(0, sock_transp->timeout * 1000);
        subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0);
        if (subreq == NULL) {
                goto fail;
        }
+
+       if (!tevent_req_set_endtime(subreq, ev, endtime)) {
+               goto fail;
+       }
+
        tevent_req_set_callback(subreq, rpc_sock_write_done, req);
        return req;
  fail:
@@ -193,6 +208,7 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int 
fd,
        result->priv = state;
 
        state->fd = fd;
+       state->timeout = 10000; /* 10 seconds. */
        talloc_set_destructor(state, rpc_transport_sock_state_destructor);
 
        result->trans_send = NULL;
@@ -205,3 +221,40 @@ NTSTATUS rpc_transport_sock_init(TALLOC_CTX *mem_ctx, int 
fd,
        *presult = result;
        return NT_STATUS_OK;
 }
+
+int rpccli_set_sock_timeout(struct rpc_pipe_client *cli, int timeout)
+{
+       struct rpc_transport_sock_state *state = 
talloc_get_type(cli->transport->priv,
+                                                       struct 
rpc_transport_sock_state);
+       int orig_timeout;
+       if (!state) {
+               return 0;
+       }
+       orig_timeout = state->timeout;
+       state->timeout = timeout;
+       return orig_timeout;
+}
+
+void rpccli_close_sock_fd(struct rpc_pipe_client *cli)
+{
+       struct rpc_transport_sock_state *state = 
talloc_get_type(cli->transport->priv,
+                                                       struct 
rpc_transport_sock_state);
+       if (state) {
+               if (state->fd != -1) {
+                       close(state->fd);
+                       state->fd = -1;
+               }
+       }
+       return;
+}
+
+bool rpc_pipe_tcp_connection_ok(struct rpc_pipe_client *cli)
+{
+       struct rpc_transport_sock_state *state = 
talloc_get_type(cli->transport->priv,
+                                                       struct 
rpc_transport_sock_state);
+       if (state && state->fd != -1) {
+               return true;
+       }
+
+       return false;
+}
diff --git a/source3/winbindd/winbindd_cache.c 
b/source3/winbindd/winbindd_cache.c
index ddbd9d9..68972dd 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -1380,6 +1380,7 @@ static NTSTATUS query_user_list(struct winbindd_domain 
*domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i, retry;
+       bool old_status = domain->online;
 
        if (!cache->tdb)
                goto do_query;
@@ -1388,6 +1389,7 @@ static NTSTATUS query_user_list(struct winbindd_domain 
*domain,
        if (!centry)
                goto do_query;
 
+do_fetch_cache:
        *num_entries = centry_uint32(centry);
 
        if (*num_entries == 0)
@@ -1448,12 +1450,44 @@ do_query:
                                  "connection cache\n"));
                        invalidate_cm_connection(&domain->conn);
                }
+               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+                   NT_STATUS_EQUAL(status, 
NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+                       if (!domain->internal && old_status) {
+                               set_domain_offline(domain);
+                       }
+                       /* store partial response. */
+                       if (*num_entries > 0) {
+                               /*
+                                * humm, what about the status used for cache?
+                                * Should it be NT_STATUS_OK?
+                                */
+                               break;
+                       }
+                       /*
+                        * domain is offline now, and there is no user entries,
+                        * try to fetch from cache again.
+                        */
+                       if (cache->tdb && !domain->online && !domain->internal 
&& old_status) {
+                               centry = wcache_fetch(cache, domain, "UL/%s", 
domain->name);
+                               /* partial response... */
+                               if (!centry) {
+                                       goto skip_save;
+                               } else {
+                                       goto do_fetch_cache;
+                               }
+                       } else {
+                               goto skip_save;
+                       }
+               }
 
        } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && 
                 (retry++ < 5));
 
        /* and save it */
        refresh_sequence_number(domain, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        centry = centry_start(domain, status);
        if (!centry)
                goto skip_save;
@@ -1497,7 +1531,9 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain 
*domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -1505,6 +1541,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain 
*domain,
        if (!centry)
                goto do_query;
 
+do_fetch_cache:
        *num_entries = centry_uint32(centry);
 
        if (*num_entries == 0)
@@ -1543,8 +1580,26 @@ do_query:
 
        status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, 
info);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (cache->tdb &&
+                       !domain->online &&
+                       !domain->internal &&
+                       old_status) {
+                       centry = wcache_fetch(cache, domain, "GL/%s/domain", 
domain->name);
+                       if (centry) {
+                               goto do_fetch_cache;
+                       }
+               }
+       }
        /* and save it */
        refresh_sequence_number(domain, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        centry = centry_start(domain, status);
        if (!centry)
                goto skip_save;
@@ -1571,7 +1626,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain 
*domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -1579,6 +1636,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain 
*domain,
        if (!centry)
                goto do_query;
 
+do_fetch_cache:
        *num_entries = centry_uint32(centry);
 
        if (*num_entries == 0)
@@ -1627,8 +1685,26 @@ do_query:
 
        status = domain->backend->enum_local_groups(domain, mem_ctx, 
num_entries, info);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+               NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) 
{
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (cache->tdb &&
+                       !domain->internal &&
+                       !domain->online &&
+                       old_status) {
+                       centry = wcache_fetch(cache, domain, "GL/%s/local", 
domain->name);
+                       if (centry) {
+                               goto do_fetch_cache;
+                       }
+               }
+       }
        /* and save it */
        refresh_sequence_number(domain, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        centry = centry_start(domain, status);
        if (!centry)
                goto skip_save;
@@ -1694,6 +1770,9 @@ static NTSTATUS name_to_sid(struct winbindd_domain 
*domain,
                            enum lsa_SidType *type)
 {
        NTSTATUS status;
+       bool old_status;
+
+       old_status = domain->online;
 
        status = wcache_name_to_sid(domain, domain_name, name, sid, type);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -1719,6 +1798,19 @@ static NTSTATUS name_to_sid(struct winbindd_domain 
*domain,
        status = domain->backend->name_to_sid(domain, mem_ctx, domain_name,
                                              name, flags, sid, type);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+               NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) 
{
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (!domain->internal &&
+                       !domain->online &&
+                       old_status) {
+                       NTSTATUS cache_status;
+                       cache_status = wcache_name_to_sid(domain, domain_name, 
name, sid, type);
+                       return cache_status;
+               }
+       }
        /* and save it */
        refresh_sequence_number(domain, false);
 
@@ -1789,7 +1881,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain 
*domain,
                            enum lsa_SidType *type)
 {
        NTSTATUS status;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_sid_to_name(domain, sid, mem_ctx, domain_name, name,
                                    type);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -1815,8 +1909,25 @@ static NTSTATUS sid_to_name(struct winbindd_domain 
*domain,
 
        status = domain->backend->sid_to_name(domain, mem_ctx, sid, 
domain_name, name, type);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+               NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) 
{
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (!domain->internal &&
+                       !domain->online &&
+                       old_status) {
+                       NTSTATUS cache_status;
+                       cache_status = wcache_sid_to_name(domain, sid, mem_ctx,
+                                                       domain_name, name, 
type);
+                       return cache_status;
+               }
+       }
        /* and save it */
        refresh_sequence_number(domain, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, 
*type);
 
        /* We can't save the name to sid mapping here, as with sid history a
@@ -1839,7 +1950,9 @@ static NTSTATUS rids_to_names(struct winbindd_domain 
*domain,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        bool have_mapped;
        bool have_unmapped;
+       bool old_status;
 
+       old_status = domain->online;
        *domain_name = NULL;
        *names = NULL;
        *types = NULL;
@@ -1924,6 +2037,73 @@ static NTSTATUS rids_to_names(struct winbindd_domain 
*domain,
                                                rids, num_rids, domain_name,
                                                names, types);
 
+       if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
+               NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) 
{
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (cache->tdb &&
+                       !domain->internal &&
+                       !domain->online &&
+                       old_status) {
+                       have_mapped = have_unmapped = false;
+
+                       for (i=0; i<num_rids; i++) {
+                               DOM_SID sid;
+                               struct cache_entry *centry;
+                               fstring tmp;
+
+                               if (!sid_compose(&sid, domain_sid, rids[i])) {
+                                       result = NT_STATUS_INTERNAL_ERROR;
+                                       goto error;
+                               }
+
+                               centry = wcache_fetch(cache, domain, "SN/%s",
+                                                     sid_to_fstring(tmp, 
&sid));


-- 
Samba Shared Repository

Reply via email to