s3:lib/conn_tdb: implement connections_forall_read() based on smbXsrv_*_global_traverse()
authorGregor Beck <gbeck@sernet.de>
Mon, 3 Sep 2012 09:13:16 +0000 (11:13 +0200)
committerMichael Adam <obnox@samba.org>
Fri, 19 Oct 2012 10:15:02 +0000 (12:15 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Michael Adam <obnox@samba.org>
source3/lib/conn_tdb.c
source3/lib/conn_tdb.h

index 0a622de1c6661c218da29c5230a850086b1bd3ed..3930e2736a5593a22142a2991b2bdc1d357f9682 100644 (file)
 #include "smbd/globals.h"
 #include "dbwrap/dbwrap.h"
 #include "dbwrap/dbwrap_open.h"
+#include "dbwrap/dbwrap_rbt.h"
 #include "messages.h"
 #include "lib/conn_tdb.h"
+#include "util_tdb.h"
 
 static struct db_context *connections_db_ctx(bool rw)
 {
@@ -81,31 +83,88 @@ struct db_record *connections_fetch_entry(TALLOC_CTX *mem_ctx,
        return connections_fetch_entry_ext(mem_ctx, id, conn->cnum, name);
 }
 
-struct conn_traverse_read_state {
+struct connections_forall_state {
+       struct db_context *session_by_pid;
        int (*fn)(const struct connections_key *key,
                  const struct connections_data *data,
                  void *private_data);
        void *private_data;
+       int count;
+};
+
+struct connections_forall_session {
+       uid_t uid;
+       gid_t gid;
+       char machine[FSTRING_LEN];
+       char addr[FSTRING_LEN];
 };
 
-static int connections_forall_read_fn(struct db_record *rec,
-                                     void *private_data)
+static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
+                              void *connections_forall_state)
 {
-       TDB_DATA key;
-       TDB_DATA value;
-       struct conn_traverse_read_state *state =
-               (struct conn_traverse_read_state *)private_data;
+       NTSTATUS status;
+       struct connections_forall_state *state =
+               (struct connections_forall_state*)connections_forall_state;
+
+       uint32_t id = global->session_global_id;
+       struct connections_forall_session sess;
+
+       sess.uid = global->auth_session_info->unix_token->uid;
+       sess.gid = global->auth_session_info->unix_token->gid;
+       strncpy(sess.machine, global->channels[0].remote_name, sizeof(sess.machine));
+       strncpy(sess.addr, global->channels[0].remote_address, sizeof(sess.addr));
+
+       status = dbwrap_store(state->session_by_pid,
+                             make_tdb_data((void*)&id, sizeof(id)),
+                             make_tdb_data((void*)&sess, sizeof(sess)),
+                             TDB_INSERT);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to store record: %s\n", nt_errstr(status)));
+       }
+       return 0;
+}
+
+static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
+                           void *connections_forall_state)
+{
+       NTSTATUS status;
+       struct connections_forall_state *state =
+               (struct connections_forall_state*)connections_forall_state;
+
+       struct connections_key key;
+       struct connections_data data;
 
-       key = dbwrap_record_get_key(rec);
-       value = dbwrap_record_get_value(rec);
+       uint32_t sess_id = global->session_global_id;
+       struct connections_forall_session sess = {
+               .uid = -1,
+               .gid = -1,
+       };
 
-       if ((key.dsize != sizeof(struct connections_key))
-           || (value.dsize != sizeof(struct connections_data))) {
-               return 0;
+       TDB_DATA val = tdb_null;
+
+       status = dbwrap_fetch(state->session_by_pid, state,
+                             make_tdb_data((void*)&sess_id, sizeof(sess_id)),
+                             &val);
+       if (NT_STATUS_IS_OK(status)) {
+               memcpy((uint8_t *)&sess, val.dptr, val.dsize);
        }
-       return state->fn((const struct connections_key *)key.dptr,
-                        (const struct connections_data *)value.dptr,
-                        state->private_data);
+
+       ZERO_STRUCT(key);
+       ZERO_STRUCT(data);
+
+       key.pid = data.pid = global->server_id;
+       key.cnum = data.cnum = global->tcon_global_id;
+       strncpy(key.name, global->share_name, sizeof(key.name));
+       strncpy(data.servicename, global->share_name, sizeof(data.servicename));
+       data.uid = sess.uid;
+       data.gid = sess.gid;
+       strncpy(data.addr, sess.addr, sizeof(data.addr));
+       strncpy(data.machine, sess.machine, sizeof(data.machine));
+       data.start = nt_time_to_unix(global->creation_time);
+
+       state->count++;
+
+       return state->fn(&key, &data, state->private_data);
 }
 
 int connections_forall_read(int (*fn)(const struct connections_key *key,
@@ -113,27 +172,32 @@ int connections_forall_read(int (*fn)(const struct connections_key *key,
                                      void *private_data),
                            void *private_data)
 {
-       struct db_context *ctx;
-       struct conn_traverse_read_state state;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct connections_forall_state *state =
+               talloc_zero(talloc_tos(), struct connections_forall_state);
        NTSTATUS status;
-       int count;
+       int ret = -1;
 
-       ctx = connections_db_ctx(false);
-       if (ctx == NULL) {
-               return -1;
+       state->session_by_pid = db_open_rbt(state);
+       state->fn = fn;
+       state->private_data = private_data;
+       status = smbXsrv_session_global_traverse(collect_sessions_fn, state);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to traverse sessions: %s\n",
+                         nt_errstr(status)));
+               goto done;
        }
 
-       state.fn = fn;
-       state.private_data = private_data;
-
-       status = dbwrap_traverse_read(ctx, connections_forall_read_fn,
-                                     (void *)&state, &count);
-
+       status = smbXsrv_tcon_global_traverse(traverse_tcon_fn, state);
        if (!NT_STATUS_IS_OK(status)) {
-               return -1;
+               DEBUG(0, ("Failed to traverse tree connects: %s\n",
+                         nt_errstr(status)));
+               goto done;
        }
-
-       return count;
+       ret = state->count;
+done:
+       talloc_free(frame);
+       return ret;
 }
 
 bool connections_init(bool rw)
index 180a5e23fd6d2d7a5d45117523057cd744a6ee08..2f45281a819976fbc3a9346f8daad0c2ba56814d 100644 (file)
@@ -25,21 +25,14 @@ struct connections_key {
 };
 
 struct connections_data {
-       int magic;
        struct server_id pid;
        int cnum;
        uid_t uid;
        gid_t gid;
        char servicename[FSTRING_LEN];
-       char addr[24];
+       char addr[FSTRING_LEN];
        char machine[FSTRING_LEN];
        time_t start;
-
-       /*
-        * This field used to hold the msg_flags. For compatibility reasons,
-        * keep the data structure in the tdb file the same.
-        */
-       uint32 unused_compatitibility_field;
 };
 
 /* The following definitions come from lib/conn_tdb.c  */