LCOV - code coverage report
Current view: top level - source3/utils - net_serverid.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 0 328 0.0 %
Date: 2024-02-28 12:06:22 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           0 :         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           0 :                 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           0 :                 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           0 :                 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           0 :         struct wipedbs_server_data *sd;
     133           0 :         struct wipedbs_record_marker *rec;
     134           0 :         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           0 :         struct wipedbs_server_data *sd;
     188           0 :         struct wipedbs_record_marker *rec;
     189           0 :         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 db_record *db_rec,
     236             :                                  struct smbXsrv_open_global0 *open,
     237             :                                  void *wipedbs_state)
     238             : {
     239           0 :         struct wipedbs_state *state =
     240           0 :                 talloc_get_type_abort(wipedbs_state,
     241             :                 struct wipedbs_state);
     242           0 :         struct wipedbs_server_data *sd;
     243           0 :         struct wipedbs_record_marker *rec;
     244           0 :         TDB_DATA tmp;
     245           0 :         int ret = -1;
     246             : 
     247           0 :         state->stat.open.total++;
     248             : 
     249           0 :         sd = get_server_data(state, &open->server_id);
     250           0 :         if (sd == NULL) {
     251           0 :                 goto done;
     252             :         }
     253             : 
     254           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     255           0 :                 struct timeval disconnect_time;
     256           0 :                 int64_t tdiff;
     257           0 :                 bool reached;
     258             : 
     259           0 :                 state->stat.open.disconnected++;
     260             : 
     261           0 :                 nttime_to_timeval(&disconnect_time, open->disconnect_time);
     262           0 :                 tdiff = usec_time_diff(&state->now, &disconnect_time);
     263           0 :                 reached = (tdiff >= INT64_C(1000)*open->durable_timeout_msec);
     264             : 
     265           0 :                 if (state->verbose) {
     266           0 :                         TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
     267           0 :                         enum ndr_err_code ndr_err;
     268           0 :                         struct vfs_default_durable_cookie cookie;
     269             : 
     270           0 :                         ndr_err = ndr_pull_struct_blob(
     271           0 :                                 &open->backend_cookie, mem_ctx, &cookie,
     272             :                                 (ndr_pull_flags_fn_t)ndr_pull_vfs_default_durable_cookie);
     273           0 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     274           0 :                                 d_printf("ndr_pull_struct_blob failed\n");
     275           0 :                                 ret = -1;
     276           0 :                                 goto done;
     277             :                         }
     278             : 
     279           0 :                         d_printf("open[%s/%s id: 0x%" PRIx32 "] disconnected at "
     280             :                                  "[%s] %us ago with timeout of %us "
     281             :                                  "-%s reached\n",
     282             :                                  cookie.servicepath, cookie.base_name,
     283             :                                  open->open_global_id,
     284             :                                  nt_time_string(mem_ctx, open->disconnect_time),
     285           0 :                                  (unsigned)(tdiff/1000000),
     286           0 :                                  open->durable_timeout_msec / 1000,
     287             :                                  reached ? "" : " not");
     288           0 :                         talloc_free(mem_ctx);
     289             :                 }
     290             : 
     291           0 :                 if (!reached) {
     292           0 :                         ret = 0;
     293           0 :                         goto done;
     294             :                 }
     295           0 :                 state->stat.open_timed_out++;
     296             :         }
     297             : 
     298           0 :         rec = talloc_zero(sd, struct wipedbs_record_marker);
     299           0 :         if (rec == NULL) {
     300           0 :                 DEBUG(0, ("Out of memory!\n"));
     301           0 :                 goto done;
     302             :         }
     303             : 
     304           0 :         tmp = dbwrap_record_get_key(db_rec);
     305           0 :         rec->key = tdb_data_talloc_copy(rec, tmp);
     306           0 :         tmp = dbwrap_record_get_value(db_rec);
     307           0 :         rec->val = tdb_data_talloc_copy(rec, tmp);
     308             : 
     309           0 :         rec->desc = talloc_asprintf(
     310             :                 rec, "open[global: %u persistent: %llu volatile: %llu]",
     311             :                 open->open_global_id,
     312           0 :                 (long long unsigned)open->open_persistent_id,
     313           0 :                 (long long unsigned)open->open_volatile_id);
     314             : 
     315           0 :         if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
     316           0 :             (rec->desc == NULL))
     317             :         {
     318           0 :                 DEBUG(0, ("Out of memory!\n"));
     319           0 :                 goto done;
     320             :         }
     321             : 
     322           0 :         state->open_db = dbwrap_record_get_db(db_rec);
     323             : 
     324           0 :         DLIST_ADD(sd->open_records, rec);
     325           0 :         ret = 0;
     326             : 
     327           0 : done:
     328           0 :         return ret;
     329             : }
     330             : 
     331           0 : static int wipedbs_traverse_nop(struct db_record *rec, void *private_data)
     332             : {
     333           0 :         return 0;
     334             : }
     335             : 
     336           0 : static int wipedbs_traverse_fill_ids(struct db_record *rec, void *wipedbs_state)
     337             : {
     338           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     339             :                 wipedbs_state, struct wipedbs_state);
     340             : 
     341           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     342             : 
     343           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     344             :                 *(void**)val.dptr, struct wipedbs_server_data);
     345             : 
     346           0 :         state->server_ids[state->idx] = sd->server_id;
     347           0 :         state->idx++;
     348           0 :         return 0;
     349             : }
     350             : 
     351           0 : static int wipedbs_traverse_set_exists(struct db_record *rec,
     352             :                                        void *wipedbs_state)
     353             : {
     354           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     355             :                 wipedbs_state, struct wipedbs_state);
     356             : 
     357           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     358             : 
     359           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     360             :                 *(void**)val.dptr, struct wipedbs_server_data);
     361             : 
     362             :         /* assume a stable traverse order for rbt */
     363           0 :         SMB_ASSERT(server_id_equal(&state->server_ids[state->idx],
     364             :                                    &sd->server_id));
     365           0 :         sd->exists = state->server_exists[state->idx];
     366             : 
     367           0 :         if (sd->exists) {
     368           0 :                 state->stat.server.existing++;
     369             :         }
     370           0 :         if (server_id_is_disconnected(&sd->server_id)) {
     371           0 :                 state->stat.server.disconnected++;
     372             :         }
     373             : 
     374           0 :         state->idx++;
     375           0 :         return 0;
     376             : }
     377             : 
     378           0 : static bool serverids_exist(const struct server_id *ids, int num_ids,
     379             :                             bool *results)
     380             : {
     381           0 :         int i;
     382             : 
     383           0 :         for (i=0; i<num_ids; i++) {
     384           0 :                 results[i] = serverid_exists(&ids[i]);
     385             :         }
     386             : 
     387           0 :         return true;
     388             : }
     389             : 
     390             : 
     391           0 : static NTSTATUS wipedbs_check_server_exists(struct wipedbs_state *state)
     392             : {
     393           0 :         NTSTATUS status;
     394           0 :         bool ok;
     395           0 :         int num_servers;
     396             : 
     397           0 :         status = dbwrap_traverse_read(state->id2server_data,
     398             :                                       wipedbs_traverse_nop, NULL, &num_servers);
     399           0 :         if (!NT_STATUS_IS_OK(status)) {
     400           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     401           0 :                 goto done;
     402             :         }
     403           0 :         state->stat.server.total = num_servers;
     404             : 
     405           0 :         state->server_ids = talloc_array(state, struct server_id, num_servers);
     406           0 :         state->server_exists = talloc_array(state, bool, num_servers);
     407           0 :         if (state->server_ids == NULL || state->server_exists == NULL) {
     408           0 :                 DEBUG(0, ("Out of memory\n"));
     409           0 :                 goto done;
     410             :         }
     411             : 
     412           0 :         state->idx = 0;
     413           0 :         status = dbwrap_traverse_read(state->id2server_data,
     414             :                                       wipedbs_traverse_fill_ids,
     415             :                                       state, NULL);
     416           0 :         if (!NT_STATUS_IS_OK(status)) {
     417           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     418           0 :                 goto done;
     419             :         }
     420             : 
     421           0 :         ok = serverids_exist(state->server_ids, num_servers, state->server_exists);
     422           0 :         if (!ok) {
     423           0 :                 DEBUG(0, ("Calling serverids_exist failed\n"));
     424           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     425           0 :                 goto done;
     426             :         }
     427             : 
     428           0 :         state->idx = 0;
     429           0 :         status = dbwrap_traverse_read(state->id2server_data,
     430             :                                       wipedbs_traverse_set_exists, state, NULL);
     431           0 :         if (!NT_STATUS_IS_OK(status)) {
     432           0 :                 DEBUG(0, ("Failed to traverse temporary database\n"));
     433           0 :                 goto done;
     434             :         }
     435           0 : done:
     436           0 :         TALLOC_FREE(state->server_ids);
     437           0 :         TALLOC_FREE(state->server_exists);
     438           0 :         return status;
     439             : }
     440             : 
     441             : struct wipedbs_delete_state {
     442             :         struct wipedbs_record_marker *cur;
     443             :         bool verbose;
     444             :         bool dry_run;
     445             :         size_t total;
     446             :         size_t num;
     447             : };
     448             : 
     449           0 : static void wipedbs_delete_fn(
     450             :         struct db_record *rec, TDB_DATA value, void *private_data)
     451             : {
     452           0 :         struct db_context *db = dbwrap_record_get_db(rec);
     453           0 :         struct wipedbs_delete_state *state = private_data;
     454           0 :         struct wipedbs_record_marker *cur = state->cur;
     455           0 :         NTSTATUS status = NT_STATUS_OK;
     456             : 
     457           0 :         state->total += 1;
     458             : 
     459           0 :         if (!tdb_data_equal(value, cur->val)) {
     460           0 :                 DBG_ERR("Warning: record <%s> from %s changed,"
     461             :                         "skip record!\n",
     462             :                         cur->desc, dbwrap_name(db));
     463           0 :                 return;
     464             :         }
     465             : 
     466           0 :         if (state->verbose) {
     467           0 :                 d_printf("deleting %s\n", cur->desc);
     468             :         }
     469             : 
     470           0 :         if (!state->dry_run) {
     471           0 :                 status = dbwrap_record_delete(rec);
     472             :         }
     473             : 
     474           0 :         if (!NT_STATUS_IS_OK(status)) {
     475           0 :                 DBG_ERR("Failed to delete record <%s> from %s: %s\n",
     476             :                         cur->desc,
     477             :                         dbwrap_name(db),
     478             :                         nt_errstr(status));
     479           0 :                 return;
     480             :         }
     481             : 
     482           0 :         state->num += 1;
     483             : }
     484             : 
     485           0 : static int wipedbs_delete_records(struct db_context *db,
     486             :                                   struct wipedbs_record_marker *records,
     487             :                                   bool dry_run, bool verbose, int *count)
     488             : {
     489           0 :         struct wipedbs_delete_state state = {
     490             :                 .verbose = verbose, .dry_run = dry_run,
     491             :         };
     492             : 
     493           0 :         if (db == NULL) {
     494           0 :                 return 0;
     495             :         }
     496             : 
     497           0 :         for (state.cur = records;
     498           0 :              state.cur != NULL;
     499           0 :              state.cur = state.cur->next) {
     500             : 
     501           0 :                 NTSTATUS status = dbwrap_do_locked(
     502           0 :                         db, state.cur->key, wipedbs_delete_fn, &state);
     503             : 
     504           0 :                 if (!NT_STATUS_IS_OK(status)) {
     505           0 :                         DBG_ERR("dbwrap_do_locked failed for record <%s> "
     506             :                                 "from %s\n",
     507             :                                 state.cur->desc,
     508             :                                 dbwrap_name(db));
     509             :                 }
     510             :         }
     511             : 
     512           0 :         if (verbose) {
     513           0 :                 d_printf("Deleted %zu of %zu records from %s\n",
     514             :                          state.num,
     515             :                          state.total,
     516             :                          dbwrap_name(db));
     517             :         }
     518             : 
     519           0 :         if (count) {
     520           0 :                 *count += state.total;
     521             :         }
     522             : 
     523           0 :         return state.total - state.num;
     524             : }
     525             : 
     526           0 : static int wipedbs_traverse_server_data(struct db_record *rec,
     527             :                                         void *wipedbs_state)
     528             : {
     529           0 :         struct wipedbs_state *state = talloc_get_type_abort(
     530             :                 wipedbs_state, struct wipedbs_state);
     531           0 :         bool dry_run = state->testmode;
     532           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     533           0 :         int ret;
     534           0 :         struct wipedbs_server_data *sd = talloc_get_type_abort(
     535             :                 *(void**)val.dptr, struct wipedbs_server_data);
     536             : 
     537           0 :         if (state->verbose) {
     538           0 :                 d_printf("Server: '%s' %s\n", sd->server_id_str,
     539           0 :                          sd->exists ?
     540             :                          "exists" :
     541             :                          "does not exist, cleaning up...");
     542             :         }
     543             : 
     544           0 :         if (sd->exists) {
     545           0 :                 return 0;
     546             :         }
     547             : 
     548           0 :         ret = wipedbs_delete_records(state->session_db, sd->session_records,
     549           0 :                                      dry_run, state->verbose,
     550             :                                      &state->stat.session.todelete);
     551           0 :         state->stat.session.failure += ret;
     552             : 
     553           0 :         ret = wipedbs_delete_records(state->tcon_db, sd->tcon_records,
     554           0 :                                      dry_run, state->verbose,
     555             :                                      &state->stat.tcon.todelete);
     556           0 :         state->stat.tcon.failure += ret;
     557             : 
     558           0 :         ret = wipedbs_delete_records(state->open_db, sd->open_records,
     559           0 :                                      dry_run, state->verbose,
     560             :                                      &state->stat.open.todelete);
     561           0 :         state->stat.open.failure += ret;
     562             : 
     563           0 :         return 0;
     564             : }
     565             : 
     566           0 : static int net_serverid_wipedbs(struct net_context *c, int argc,
     567             :                                 const char **argv)
     568             : {
     569           0 :         int ret = -1;
     570           0 :         NTSTATUS status;
     571           0 :         struct wipedbs_state *state = talloc_zero(talloc_tos(),
     572             :                                                   struct wipedbs_state);
     573             : 
     574           0 :         if (c->display_usage) {
     575           0 :                 d_printf("%s\n%s",
     576             :                          _("Usage:"),
     577             :                          _("net serverid wipedbs [--test] [--verbose]\n"));
     578           0 :                 d_printf("%s\n%s",
     579             :                          _("Example:"),
     580             :                          _("net serverid wipedbs -v\n"));
     581           0 :                 return -1;
     582             :         }
     583             : 
     584           0 :         state->now = timeval_current();
     585           0 :         state->testmode = c->opt_testmode;
     586           0 :         state->verbose = c->opt_verbose;
     587             : 
     588           0 :         state->id2server_data = db_open_rbt(state);
     589           0 :         if (state->id2server_data == NULL) {
     590           0 :                 DEBUG(0, ("Failed to open temporary database\n"));
     591           0 :                 goto done;
     592             :         }
     593             : 
     594           0 :         status = smbXsrv_session_global_traverse(wipedbs_traverse_sessions,
     595             :                                                  state);
     596           0 :         if (!NT_STATUS_IS_OK(status)) {
     597           0 :                 goto done;
     598             :         }
     599             : 
     600           0 :         status = smbXsrv_tcon_global_traverse(wipedbs_traverse_tcon, state);
     601           0 :         if (!NT_STATUS_IS_OK(status)) {
     602           0 :                 goto done;
     603             :         }
     604             : 
     605           0 :         status = smbXsrv_open_global_traverse(wipedbs_traverse_open, state);
     606           0 :         if (!NT_STATUS_IS_OK(status)) {
     607           0 :                 goto done;
     608             :         }
     609             : 
     610           0 :         status = wipedbs_check_server_exists(state);
     611           0 :         if (!NT_STATUS_IS_OK(status)) {
     612           0 :                 goto done;
     613             :         }
     614             : 
     615           0 :         status = dbwrap_traverse_read(state->id2server_data,
     616             :                                       wipedbs_traverse_server_data,
     617             :                                       state, NULL);
     618           0 :         if (!NT_STATUS_IS_OK(status)) {
     619           0 :                 DEBUG(0, ("Failed to traverse db: %s\n", nt_errstr(status)));
     620           0 :                 goto done;
     621             :         }
     622             : 
     623           0 :         d_printf("Found %d serverids, %d alive and %d disconnected\n",
     624             :                  state->stat.server.total,
     625             :                  state->stat.server.existing,
     626             :                  state->stat.server.disconnected);
     627           0 :         d_printf("Found %d sessions, %d alive and %d disconnected"
     628             :                  ", cleaned up %d of %d entries\n",
     629             :                  state->stat.session.total,
     630           0 :                  state->stat.session.total - state->stat.session.todelete,
     631             :                  state->stat.session.disconnected,
     632           0 :                  state->stat.session.todelete - state->stat.session.failure,
     633             :                  state->stat.session.todelete);
     634           0 :         d_printf("Found %d tcons, %d alive and %d disconnected"
     635             :                  ", cleaned up %d of %d entries\n",
     636             :                  state->stat.tcon.total,
     637           0 :                  state->stat.tcon.total - state->stat.tcon.todelete,
     638             :                  state->stat.tcon.disconnected,
     639           0 :                  state->stat.tcon.todelete - state->stat.tcon.failure,
     640             :                  state->stat.tcon.todelete);
     641           0 :         d_printf("Found %d opens, %d alive, %d disconnected and %d timed out"
     642             :                  ", cleaned up %d of %d entries\n",
     643             :                  state->stat.open.total,
     644           0 :                  state->stat.open.total - state->stat.open.todelete
     645           0 :                  - (state->stat.open.disconnected - state->stat.open_timed_out),
     646             :                  state->stat.open.disconnected,
     647             :                  state->stat.open_timed_out,
     648           0 :                  state->stat.open.todelete - state->stat.open.failure,
     649             :                  state->stat.open.todelete);
     650             : 
     651           0 :         ret = 0;
     652           0 : done:
     653           0 :         talloc_free(state);
     654           0 :         return ret;
     655             : }
     656             : 
     657           0 : static int net_serverid_exists(struct net_context *c, int argc,
     658             :                                const char **argv)
     659             : {
     660           0 :         struct server_id pid;
     661           0 :         bool ok;
     662             : 
     663           0 :         if ((argc != 1) || (c->display_usage)) {
     664           0 :                 d_printf("Usage:\n"
     665             :                          "net serverid exists <serverid>\n");
     666           0 :                 return -1;
     667             :         }
     668             : 
     669           0 :         pid = server_id_from_string(get_my_vnn(), argv[0]);
     670           0 :         ok = serverid_exists(&pid);
     671             : 
     672           0 :         if (ok) {
     673           0 :                 d_printf("%s exists\n", argv[0]);
     674             :         } else {
     675           0 :                 d_printf("%s does not exist\n", argv[0]);
     676             :         }
     677             : 
     678           0 :         return 0;
     679             : }
     680             : 
     681           0 : int net_serverid(struct net_context *c, int argc, const char **argv)
     682             : {
     683           0 :         struct functable func[] = {
     684             :                 {
     685             :                         "wipedbs",
     686             :                         net_serverid_wipedbs,
     687             :                         NET_TRANSPORT_LOCAL,
     688             :                         N_("Clean dead entries from temporary databases"),
     689             :                         N_("net serverid wipedbs\n"
     690             :                            "    Clean dead entries from temporary databases")
     691             :                 },
     692             :                 {
     693             :                         "exists",
     694             :                         net_serverid_exists,
     695             :                         NET_TRANSPORT_LOCAL,
     696             :                         N_("Show existence of a serverid"),
     697             :                         N_("net serverid exists <id>")
     698             :                 },
     699             :                 {NULL, NULL, 0, NULL, NULL}
     700             :         };
     701             : 
     702           0 :         return net_run_function(c, argc, argv, "net serverid", func);
     703             : }

Generated by: LCOV version 1.14