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

Generated by: LCOV version 1.14