LCOV - code coverage report
Current view: top level - source3/utils - net_serverid.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 0 302 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /*
       2             :    Samba Unix/Linux SMB client library
       3             :    net serverid commands
       4             :    Copyright (C) Volker Lendecke 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "utils/net.h"
      22             : #include "lib/util/server_id.h"
      23             : #include "dbwrap/dbwrap.h"
      24             : #include "dbwrap/dbwrap_rbt.h"
      25             : #include "serverid.h"
      26             : #include "session.h"
      27             : #include "smbd/globals.h"
      28             : #include "smbd/smbXsrv_open.h"
      29             : #include "util_tdb.h"
      30             : #include "librpc/gen_ndr/ndr_open_files.h"
      31             : 
      32             : struct wipedbs_record_marker {
      33             :         struct wipedbs_record_marker *prev, *next;
      34             :         TDB_DATA key, val;
      35             :         const char *desc;
      36             : };
      37             : 
      38             : struct wipedbs_server_data {
      39             :         struct server_id server_id;
      40             :         const char *server_id_str;
      41             :         bool exists;
      42             :         struct wipedbs_record_marker *session_records;
      43             :         struct wipedbs_record_marker *tcon_records;
      44             :         struct wipedbs_record_marker *open_records;
      45             : };
      46             : 
      47             : struct wipedbs_state {
      48             :         struct db_context *id2server_data;
      49             :         struct {
      50             :                 struct {
      51             :                         int total;
      52             :                         int existing;
      53             :                         int disconnected;
      54             :                 } server;
      55             :                 struct {
      56             :                         int total;
      57             :                         int disconnected;
      58             :                         int todelete;
      59             :                         int failure;
      60             :                 } session, tcon, open;
      61             :                 int open_timed_out;
      62             :         } stat;
      63             :         struct server_id *server_ids;
      64             :         bool *server_exists;
      65             :         int idx;
      66             :         struct db_context *session_db;
      67             :         struct db_context *tcon_db;
      68             :         struct db_context *open_db;
      69             :         struct timeval now;
      70             :         bool testmode;
      71             :         bool verbose;
      72             : };
      73             : 
      74           0 : static struct wipedbs_server_data *get_server_data(struct wipedbs_state *state,
      75             :                                                    const struct server_id *id)
      76             : {
      77           0 :         struct wipedbs_server_data *ret = NULL;
      78           0 :         TDB_DATA key, val = tdb_null;
      79             :         NTSTATUS status;
      80             : 
      81           0 :         key = make_tdb_data((const void*)&id->unique_id, sizeof(id->unique_id));
      82           0 :         status = dbwrap_fetch(state->id2server_data, talloc_tos(), key, &val);
      83           0 :         if (NT_STATUS_IS_OK(status)) {
      84           0 :                 ret = *(struct wipedbs_server_data**) val.dptr;
      85           0 :                 TALLOC_FREE(val.dptr);
      86           0 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
      87             :                 struct server_id_buf idbuf;
      88             : 
      89           0 :                 server_id_str_buf(*id, &idbuf);
      90             : 
      91           0 :                 ret = talloc_zero(state->id2server_data,
      92             :                                   struct wipedbs_server_data);
      93           0 :                 if (ret == NULL) {
      94           0 :                         DEBUG(0, ("Failed to allocate server entry for %s\n",
      95             :                                   idbuf.buf));
      96           0 :                         goto done;
      97             :                 }
      98           0 :                 ret->server_id = *id;
      99           0 :                 ret->server_id_str = talloc_strdup(ret, idbuf.buf);
     100           0 :                 ret->exists = true;
     101           0 :                 val = make_tdb_data((const void*)&ret, sizeof(ret));
     102           0 :                 status = dbwrap_store(state->id2server_data,
     103             :                                       key, val, TDB_INSERT);
     104           0 :                 if (!NT_STATUS_IS_OK(status)) {
     105           0 :                         DEBUG(0, ("Failed to store server entry for %s: %s\n",
     106             :                                   idbuf.buf, nt_errstr(status)));
     107             :                 }
     108           0 :                 goto done;
     109             :         } else {
     110             :                 struct server_id_buf idbuf;
     111           0 :                 DEBUG(0, ("Failed to fetch server entry for %s: %s\n",
     112             :                           server_id_str_buf(*id, &idbuf), nt_errstr(status)));
     113           0 :                 goto done;
     114             :         }
     115           0 :         if (!server_id_equal(id, &ret->server_id)) {
     116             :                 struct server_id_buf idbuf1, idbuf2;
     117           0 :                 DEBUG(0, ("uniq id collision for %s and %s\n",
     118             :                           server_id_str_buf(*id, &idbuf1),
     119             :                           server_id_str_buf(ret->server_id, &idbuf2)));
     120           0 :                 smb_panic("server_id->unique_id not unique!");
     121             :         }
     122           0 : done:
     123           0 :         return ret;
     124             : }
     125             : 
     126           0 : static int wipedbs_traverse_sessions(struct smbXsrv_session_global0 *session,
     127             :                                      void *wipedbs_state)
     128             : {
     129           0 :         struct wipedbs_state *state =
     130           0 :                 talloc_get_type_abort(wipedbs_state,
     131             :                 struct wipedbs_state);
     132             :         struct wipedbs_server_data *sd;
     133             :         struct wipedbs_record_marker *rec;
     134             :         TDB_DATA tmp;
     135           0 :         int ret = -1;
     136             : 
     137           0 :         assert(session->num_channels == 1);
     138             : 
     139           0 :         state->stat.session.total++;
     140             : 
     141           0 :         sd = get_server_data(state, &session->channels[0].server_id);
     142           0 :         if (sd == NULL) {
     143           0 :                 goto done;
     144             :         }
     145             : 
     146           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     147           0 :                 state->stat.session.disconnected++;
     148             :         }
     149             : 
     150           0 :         rec = talloc_zero(sd, struct wipedbs_record_marker);
     151           0 :         if (rec == NULL) {
     152           0 :                 DEBUG(0, ("Out of memory!\n"));
     153           0 :                 goto done;
     154             :         }
     155             : 
     156           0 :         tmp = dbwrap_record_get_key(session->db_rec);
     157           0 :         rec->key = tdb_data_talloc_copy(rec, tmp);
     158           0 :         tmp = dbwrap_record_get_value(session->db_rec);
     159           0 :         rec->val = tdb_data_talloc_copy(rec, tmp);
     160             : 
     161           0 :         rec->desc = talloc_asprintf(
     162             :                 rec, "session[global: %u wire: %llu]",
     163             :                 session->session_global_id,
     164           0 :                 (long long unsigned)session->session_wire_id);
     165             : 
     166           0 :         if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
     167           0 :             (rec->desc == NULL))
     168             :         {
     169           0 :                 DEBUG(0, ("Out of memory!\n"));
     170           0 :                 goto done;
     171             :         }
     172             : 
     173           0 :         state->session_db = dbwrap_record_get_db(session->db_rec);
     174             : 
     175           0 :         DLIST_ADD(sd->session_records, rec);
     176           0 :         ret = 0;
     177           0 : done:
     178           0 :         return ret;
     179             : }
     180             : 
     181           0 : static int wipedbs_traverse_tcon(struct smbXsrv_tcon_global0 *tcon,
     182             :                                  void *wipedbs_state)
     183             : {
     184           0 :         struct wipedbs_state *state =
     185           0 :                 talloc_get_type_abort(wipedbs_state,
     186             :                 struct wipedbs_state);
     187             :         struct wipedbs_server_data *sd;
     188             :         struct wipedbs_record_marker *rec;
     189             :         TDB_DATA tmp;
     190           0 :         int ret = -1;
     191             : 
     192           0 :         state->stat.tcon.total++;
     193             : 
     194           0 :         sd = get_server_data(state, &tcon->server_id);
     195           0 :         if (sd == NULL) {
     196           0 :                 goto done;
     197             :         }
     198             : 
     199           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     200           0 :                 state->stat.tcon.disconnected++;
     201             :         }
     202             : 
     203           0 :         rec = talloc_zero(sd, struct wipedbs_record_marker);
     204           0 :         if (rec == NULL) {
     205           0 :                 DEBUG(0, ("Out of memory!\n"));
     206           0 :                 goto done;
     207             :         }
     208             : 
     209           0 :         tmp = dbwrap_record_get_key(tcon->db_rec);
     210           0 :         rec->key = tdb_data_talloc_copy(rec, tmp);
     211           0 :         tmp = dbwrap_record_get_value(tcon->db_rec);
     212           0 :         rec->val = tdb_data_talloc_copy(rec, tmp);
     213             : 
     214           0 :         rec->desc = talloc_asprintf(
     215             :                 rec, "tcon[global: %u wire: %u session: %u share: %s]",
     216             :                 tcon->tcon_global_id, tcon->tcon_wire_id,
     217             :                 tcon->session_global_id, tcon->share_name);
     218             : 
     219           0 :         if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
     220           0 :             (rec->desc == NULL))
     221             :         {
     222           0 :                 DEBUG(0, ("Out of memory!\n"));
     223           0 :                 goto done;
     224             :         }
     225             : 
     226           0 :         state->tcon_db = dbwrap_record_get_db(tcon->db_rec);
     227             : 
     228           0 :         DLIST_ADD(sd->tcon_records, rec);
     229           0 :         ret = 0;
     230             : 
     231           0 : done:
     232           0 :         return ret;
     233             : }
     234             : 
     235           0 : static int wipedbs_traverse_open(struct smbXsrv_open_global0 *open,
     236             :                                  void *wipedbs_state)
     237             : {
     238           0 :         struct wipedbs_state *state =
     239           0 :                 talloc_get_type_abort(wipedbs_state,
     240             :                 struct wipedbs_state);
     241             :         struct wipedbs_server_data *sd;
     242             :         struct wipedbs_record_marker *rec;
     243             :         TDB_DATA tmp;
     244           0 :         int ret = -1;
     245             : 
     246           0 :         state->stat.open.total++;
     247             : 
     248           0 :         sd = get_server_data(state, &open->server_id);
     249           0 :         if (sd == NULL) {
     250           0 :                 goto done;
     251             :         }
     252             : 
     253           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     254             :                 struct timeval disconnect_time;
     255             :                 int64_t tdiff;
     256             :                 bool reached;
     257             : 
     258           0 :                 state->stat.open.disconnected++;
     259             : 
     260           0 :                 nttime_to_timeval(&disconnect_time, open->disconnect_time);
     261           0 :                 tdiff = usec_time_diff(&state->now, &disconnect_time);
     262           0 :                 reached = (tdiff >= 1000*open->durable_timeout_msec);
     263             : 
     264           0 :                 if (state->verbose) {
     265           0 :                         TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
     266             :                         enum ndr_err_code ndr_err;
     267             :                         struct vfs_default_durable_cookie cookie;
     268             : 
     269           0 :                         ndr_err = ndr_pull_struct_blob(
     270           0 :                                 &open->backend_cookie, mem_ctx, &cookie,
     271             :                                 (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie);
     272           0 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     273           0 :                                 d_printf("ndr_pull_struct_blob failed\n");
     274           0 :                                 ret = -1;
     275           0 :                                 goto done;
     276             :                         }
     277             : 
     278           0 :                         d_printf("open[%s/%s id: 0x%" PRIx32 "] disconnected at "
     279             :                                  "[%s] %us ago with timeout of %us "
     280             :                                  "-%s reached\n",
     281             :                                  cookie.servicepath, cookie.base_name,
     282             :                                  open->open_global_id,
     283             :                                  nt_time_string(mem_ctx, open->disconnect_time),
     284           0 :                                  (unsigned)(tdiff/1000000),
     285           0 :                                  open->durable_timeout_msec / 1000,
     286             :                                  reached ? "" : " not");
     287           0 :                         talloc_free(mem_ctx);
     288             :                 }
     289             : 
     290           0 :                 if (!reached) {
     291           0 :                         ret = 0;
     292           0 :                         goto done;
     293             :                 }
     294           0 :                 state->stat.open_timed_out++;
     295             :         }
     296             : 
     297           0 :         rec = talloc_zero(sd, struct wipedbs_record_marker);
     298           0 :         if (rec == NULL) {
     299           0 :                 DEBUG(0, ("Out of memory!\n"));
     300           0 :                 goto done;
     301             :         }
     302             : 
     303           0 :         tmp = dbwrap_record_get_key(open->db_rec);
     304           0 :         rec->key = tdb_data_talloc_copy(rec, tmp);
     305           0 :         tmp = dbwrap_record_get_value(open->db_rec);
     306           0 :         rec->val = tdb_data_talloc_copy(rec, tmp);
     307             : 
     308           0 :         rec->desc = talloc_asprintf(
     309             :                 rec, "open[global: %u persistent: %llu volatile: %llu]",
     310             :                 open->open_global_id,
     311           0 :                 (long long unsigned)open->open_persistent_id,
     312           0 :                 (long long unsigned)open->open_volatile_id);
     313             : 
     314           0 :         if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
     315           0 :             (rec->desc == NULL))
     316             :         {
     317           0 :                 DEBUG(0, ("Out of memory!\n"));
     318           0 :                 goto done;
     319             :         }
     320             : 
     321           0 :         state->open_db = dbwrap_record_get_db(open->db_rec);
     322             : 
     323           0 :         DLIST_ADD(sd->open_records, rec);
     324           0 :         ret = 0;
     325             : 
     326           0 : done:
     327           0 :         return ret;
     328             : }
     329             : 
     330           0 : static int wipedbs_traverse_nop(struct db_record *rec, void *private_data)
     331             : {
     332           0 :         return 0;
     333             : }
     334             : 
     335           0 : static int wipedbs_traverse_fill_ids(struct db_record *rec, void *wipedbs_state)
     336             : {
     337           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     338             :                 wipedbs_state, struct wipedbs_state);
     339             : 
     340           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     341             : 
     342           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     343             :                 *(void**)val.dptr, struct wipedbs_server_data);
     344             : 
     345           0 :         state->server_ids[state->idx] = sd->server_id;
     346           0 :         state->idx++;
     347           0 :         return 0;
     348             : }
     349             : 
     350           0 : static int wipedbs_traverse_set_exists(struct db_record *rec,
     351             :                                        void *wipedbs_state)
     352             : {
     353           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     354             :                 wipedbs_state, struct wipedbs_state);
     355             : 
     356           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     357             : 
     358           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     359             :                 *(void**)val.dptr, struct wipedbs_server_data);
     360             : 
     361             :         /* assume a stable traverse order for rbt */
     362           0 :         SMB_ASSERT(server_id_equal(&state->server_ids[state->idx],
     363             :                                    &sd->server_id));
     364           0 :         sd->exists = state->server_exists[state->idx];
     365             : 
     366           0 :         if (sd->exists) {
     367           0 :                 state->stat.server.existing++;
     368             :         }
     369           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     370           0 :                 state->stat.server.disconnected++;
     371             :         }
     372             : 
     373           0 :         state->idx++;
     374           0 :         return 0;
     375             : }
     376             : 
     377           0 : static bool serverids_exist(const struct server_id *ids, int num_ids,
     378             :                             bool *results)
     379             : {
     380             :         int i;
     381             : 
     382           0 :         for (i=0; i<num_ids; i++) {
     383           0 :                 results[i] = serverid_exists(&ids[i]);
     384             :         }
     385             : 
     386           0 :         return true;
     387             : }
     388             : 
     389             : 
     390           0 : static NTSTATUS wipedbs_check_server_exists(struct wipedbs_state *state)
     391             : {
     392             :         NTSTATUS status;
     393             :         bool ok;
     394             :         int num_servers;
     395             : 
     396           0 :         status = dbwrap_traverse_read(state->id2server_data,
     397             :                                       wipedbs_traverse_nop, NULL, &num_servers);
     398           0 :         if (!NT_STATUS_IS_OK(status)) {
     399           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     400           0 :                 goto done;
     401             :         }
     402           0 :         state->stat.server.total = num_servers;
     403             : 
     404           0 :         state->server_ids = talloc_array(state, struct server_id, num_servers);
     405           0 :         state->server_exists = talloc_array(state, bool, num_servers);
     406           0 :         if (state->server_ids == NULL || state->server_exists == NULL) {
     407           0 :                 DEBUG(0, ("Out of memory\n"));
     408           0 :                 goto done;
     409             :         }
     410             : 
     411           0 :         state->idx = 0;
     412           0 :         status = dbwrap_traverse_read(state->id2server_data,
     413             :                                       wipedbs_traverse_fill_ids,
     414             :                                       state, NULL);
     415           0 :         if (!NT_STATUS_IS_OK(status)) {
     416           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     417           0 :                 goto done;
     418             :         }
     419             : 
     420           0 :         ok = serverids_exist(state->server_ids, num_servers, state->server_exists);
     421           0 :         if (!ok) {
     422           0 :                 DEBUG(0, ("Calling serverids_exist failed\n"));
     423           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     424           0 :                 goto done;
     425             :         }
     426             : 
     427           0 :         state->idx = 0;
     428           0 :         status = dbwrap_traverse_read(state->id2server_data,
     429             :                                       wipedbs_traverse_set_exists, state, NULL);
     430           0 :         if (!NT_STATUS_IS_OK(status)) {
     431           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     432           0 :                 goto done;
     433             :         }
     434           0 : done:
     435           0 :         TALLOC_FREE(state->server_ids);
     436           0 :         TALLOC_FREE(state->server_exists);
     437           0 :         return status;
     438             : }
     439             : 
     440             : struct wipedbs_delete_state {
     441             :         struct wipedbs_record_marker *cur;
     442             :         bool verbose;
     443             :         bool dry_run;
     444             :         size_t total;
     445             :         size_t num;
     446             : };
     447             : 
     448           0 : static void wipedbs_delete_fn(
     449             :         struct db_record *rec, TDB_DATA value, void *private_data)
     450             : {
     451           0 :         struct db_context *db = dbwrap_record_get_db(rec);
     452           0 :         struct wipedbs_delete_state *state = private_data;
     453           0 :         struct wipedbs_record_marker *cur = state->cur;
     454           0 :         NTSTATUS status = NT_STATUS_OK;
     455             : 
     456           0 :         state->total += 1;
     457             : 
     458           0 :         if (!tdb_data_equal(value, cur->val)) {
     459           0 :                 DBG_ERR("Warning: record <%s> from %s changed,"
     460             :                         "skip record!\n",
     461             :                         cur->desc, dbwrap_name(db));
     462           0 :                 return;
     463             :         }
     464             : 
     465           0 :         if (state->verbose) {
     466           0 :                 d_printf("deleting %s\n", cur->desc);
     467             :         }
     468             : 
     469           0 :         if (!state->dry_run) {
     470           0 :                 status = dbwrap_record_delete(rec);
     471             :         }
     472             : 
     473           0 :         if (!NT_STATUS_IS_OK(status)) {
     474           0 :                 DBG_ERR("Failed to delete record <%s> from %s: %s\n",
     475             :                         cur->desc,
     476             :                         dbwrap_name(db),
     477             :                         nt_errstr(status));
     478           0 :                 return;
     479             :         }
     480             : 
     481           0 :         state->num += 1;
     482             : }
     483             : 
     484           0 : static int wipedbs_delete_records(struct db_context *db,
     485             :                                   struct wipedbs_record_marker *records,
     486             :                                   bool dry_run, bool verbose, int *count)
     487             : {
     488           0 :         struct wipedbs_delete_state state = {
     489             :                 .verbose = verbose, .dry_run = dry_run,
     490             :         };
     491             : 
     492           0 :         if (db == NULL) {
     493           0 :                 return 0;
     494             :         }
     495             : 
     496           0 :         for (state.cur = records;
     497           0 :              state.cur != NULL;
     498           0 :              state.cur = state.cur->next) {
     499             : 
     500           0 :                 NTSTATUS status = dbwrap_do_locked(
     501           0 :                         db, state.cur->key, wipedbs_delete_fn, &state);
     502             : 
     503           0 :                 if (!NT_STATUS_IS_OK(status)) {
     504           0 :                         DBG_ERR("dbwrap_do_locked failed for record <%s> "
     505             :                                 "from %s\n",
     506             :                                 state.cur->desc,
     507             :                                 dbwrap_name(db));
     508             :                 }
     509             :         }
     510             : 
     511           0 :         if (verbose) {
     512           0 :                 d_printf("Deleted %zu of %zu records from %s\n",
     513             :                          state.num,
     514             :                          state.total,
     515             :                          dbwrap_name(db));
     516             :         }
     517             : 
     518           0 :         if (count) {
     519           0 :                 *count += state.total;
     520             :         }
     521             : 
     522           0 :         return state.total - state.num;
     523             : }
     524             : 
     525           0 : static int wipedbs_traverse_server_data(struct db_record *rec,
     526             :                                         void *wipedbs_state)
     527             : {
     528           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     529             :                 wipedbs_state, struct wipedbs_state);
     530           0 :         bool dry_run = state->testmode;
     531           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     532             :         int ret;
     533           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     534             :                 *(void**)val.dptr, struct wipedbs_server_data);
     535             : 
     536           0 :         if (state->verbose) {
     537           0 :                 d_printf("Server: '%s' %s\n", sd->server_id_str,
     538           0 :                          sd->exists ?
     539             :                          "exists" :
     540             :                          "does not exist, cleaning up...");
     541             :         }
     542             : 
     543           0 :         if (sd->exists) {
     544           0 :                 return 0;
     545             :         }
     546             : 
     547           0 :         ret = wipedbs_delete_records(state->session_db, sd->session_records,
     548           0 :                                      dry_run, state->verbose,
     549             :                                      &state->stat.session.todelete);
     550           0 :         state->stat.session.failure += ret;
     551             : 
     552           0 :         ret = wipedbs_delete_records(state->tcon_db, sd->tcon_records,
     553           0 :                                      dry_run, state->verbose,
     554             :                                      &state->stat.tcon.todelete);
     555           0 :         state->stat.tcon.failure += ret;
     556             : 
     557           0 :         ret = wipedbs_delete_records(state->open_db, sd->open_records,
     558           0 :                                      dry_run, state->verbose,
     559             :                                      &state->stat.open.todelete);
     560           0 :         state->stat.open.failure += ret;
     561             : 
     562           0 :         return 0;
     563             : }
     564             : 
     565           0 : static int net_serverid_wipedbs(struct net_context *c, int argc,
     566             :                                 const char **argv)
     567             : {
     568           0 :         int ret = -1;
     569             :         NTSTATUS status;
     570           0 :         struct wipedbs_state *state = talloc_zero(talloc_tos(),
     571             :                                                   struct wipedbs_state);
     572             : 
     573           0 :         if (c->display_usage) {
     574           0 :                 d_printf("%s\n%s",
     575             :                          _("Usage:"),
     576             :                          _("net serverid wipedbs [--test] [--verbose]\n"));
     577           0 :                 d_printf("%s\n%s",
     578             :                          _("Example:"),
     579             :                          _("net serverid wipedbs -v\n"));
     580           0 :                 return -1;
     581             :         }
     582             : 
     583           0 :         state->now = timeval_current();
     584           0 :         state->testmode = c->opt_testmode;
     585           0 :         state->verbose = c->opt_verbose;
     586             : 
     587           0 :         state->id2server_data = db_open_rbt(state);
     588           0 :         if (state->id2server_data == NULL) {
     589           0 :                 DEBUG(0, ("Failed to open temporary database\n"));
     590           0 :                 goto done;
     591             :         }
     592             : 
     593           0 :         status = smbXsrv_session_global_traverse(wipedbs_traverse_sessions,
     594             :                                                  state);
     595           0 :         if (!NT_STATUS_IS_OK(status)) {
     596           0 :                 goto done;
     597             :         }
     598             : 
     599           0 :         status = smbXsrv_tcon_global_traverse(wipedbs_traverse_tcon, state);
     600           0 :         if (!NT_STATUS_IS_OK(status)) {
     601           0 :                 goto done;
     602             :         }
     603             : 
     604           0 :         status = smbXsrv_open_global_traverse(wipedbs_traverse_open, state);
     605           0 :         if (!NT_STATUS_IS_OK(status)) {
     606           0 :                 goto done;
     607             :         }
     608             : 
     609           0 :         status = wipedbs_check_server_exists(state);
     610           0 :         if (!NT_STATUS_IS_OK(status)) {
     611           0 :                 goto done;
     612             :         }
     613             : 
     614           0 :         status = dbwrap_traverse_read(state->id2server_data,
     615             :                                       wipedbs_traverse_server_data,
     616             :                                       state, NULL);
     617           0 :         if (!NT_STATUS_IS_OK(status)) {
     618           0 :                 DEBUG(0, ("Failed to traverse db: %s\n", nt_errstr(status)));
     619           0 :                 goto done;
     620             :         }
     621             : 
     622           0 :         d_printf("Found %d serverids, %d alive and %d disconnected\n",
     623             :                  state->stat.server.total,
     624             :                  state->stat.server.existing,
     625             :                  state->stat.server.disconnected);
     626           0 :         d_printf("Found %d sessions, %d alive and %d disconnected"
     627             :                  ", cleaned up %d of %d entries\n",
     628             :                  state->stat.session.total,
     629           0 :                  state->stat.session.total - state->stat.session.todelete,
     630             :                  state->stat.session.disconnected,
     631           0 :                  state->stat.session.todelete - state->stat.session.failure,
     632             :                  state->stat.session.todelete);
     633           0 :         d_printf("Found %d tcons, %d alive and %d disconnected"
     634             :                  ", cleaned up %d of %d entries\n",
     635             :                  state->stat.tcon.total,
     636           0 :                  state->stat.tcon.total - state->stat.tcon.todelete,
     637             :                  state->stat.tcon.disconnected,
     638           0 :                  state->stat.tcon.todelete - state->stat.tcon.failure,
     639             :                  state->stat.tcon.todelete);
     640           0 :         d_printf("Found %d opens, %d alive, %d disconnected and %d timed out"
     641             :                  ", cleaned up %d of %d entries\n",
     642             :                  state->stat.open.total,
     643           0 :                  state->stat.open.total - state->stat.open.todelete
     644           0 :                  - (state->stat.open.disconnected - state->stat.open_timed_out),
     645             :                  state->stat.open.disconnected,
     646             :                  state->stat.open_timed_out,
     647           0 :                  state->stat.open.todelete - state->stat.open.failure,
     648             :                  state->stat.open.todelete);
     649             : 
     650           0 :         ret = 0;
     651           0 : done:
     652           0 :         talloc_free(state);
     653           0 :         return ret;
     654             : }
     655             : 
     656           0 : static int net_serverid_exists(struct net_context *c, int argc,
     657             :                                const char **argv)
     658             : {
     659             :         struct server_id pid;
     660             :         bool ok;
     661             : 
     662           0 :         if ((argc != 1) || (c->display_usage)) {
     663           0 :                 d_printf("Usage:\n"
     664             :                          "net serverid exists <serverid>\n");
     665           0 :                 return -1;
     666             :         }
     667             : 
     668           0 :         pid = server_id_from_string(get_my_vnn(), argv[0]);
     669           0 :         ok = serverid_exists(&pid);
     670             : 
     671           0 :         if (ok) {
     672           0 :                 d_printf("%s exists\n", argv[0]);
     673             :         } else {
     674           0 :                 d_printf("%s does not exist\n", argv[0]);
     675             :         }
     676             : 
     677           0 :         return 0;
     678             : }
     679             : 
     680           0 : int net_serverid(struct net_context *c, int argc, const char **argv)
     681             : {
     682           0 :         struct functable func[] = {
     683             :                 {
     684             :                         "wipedbs",
     685             :                         net_serverid_wipedbs,
     686             :                         NET_TRANSPORT_LOCAL,
     687             :                         N_("Clean dead entries from temporary databases"),
     688             :                         N_("net serverid wipedbs\n"
     689             :                            "    Clean dead entries from temporary databases")
     690             :                 },
     691             :                 {
     692             :                         "exists",
     693             :                         net_serverid_exists,
     694             :                         NET_TRANSPORT_LOCAL,
     695             :                         N_("Show existence of a serverid"),
     696             :                         N_("net serverid exists <id>")
     697             :                 },
     698             :                 {NULL, NULL, 0, NULL, NULL}
     699             :         };
     700             : 
     701           0 :         return net_run_function(c, argc, argv, "net serverid", func);
     702             : }

Generated by: LCOV version 1.13