Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/locking/leases_db.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   Unix SMB/CIFS implementation.
3
   Map lease keys to file ids
4
   Copyright (C) Volker Lendecke 2013
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
21
#include "includes.h"
22
#include "system/filesys.h"
23
#include "locking/leases_db.h"
24
#include "dbwrap/dbwrap.h"
25
#include "dbwrap/dbwrap_open.h"
26
#include "util_tdb.h"
27
#include "ndr.h"
28
#include "librpc/gen_ndr/ndr_leases_db.h"
29
30
#undef DBGC_CLASS
31
0
#define DBGC_CLASS DBGC_LOCKING
32
33
/* the leases database handle */
34
static struct db_context *leases_db;
35
36
bool leases_db_init(bool read_only)
37
0
{
38
0
  char *db_path;
39
40
0
  if (leases_db) {
41
0
    return true;
42
0
  }
43
44
0
  db_path = lock_path(talloc_tos(), "leases.tdb");
45
0
  if (db_path == NULL) {
46
0
    return false;
47
0
  }
48
49
0
  leases_db = db_open(NULL, db_path,
50
0
          SMBD_VOLATILE_TDB_HASH_SIZE,
51
0
          SMBD_VOLATILE_TDB_FLAGS |
52
0
          TDB_SEQNUM,
53
0
          read_only ? O_RDONLY : O_RDWR|O_CREAT, 0644,
54
0
          DBWRAP_LOCK_ORDER_4, DBWRAP_FLAG_NONE);
55
0
  TALLOC_FREE(db_path);
56
0
  if (leases_db == NULL) {
57
0
    DEBUG(1, ("ERROR: Failed to initialise leases database\n"));
58
0
    return false;
59
0
  }
60
61
0
  return true;
62
0
}
63
64
struct leases_db_key_buf {
65
  uint8_t buf[32];
66
};
67
68
static TDB_DATA leases_db_key(struct leases_db_key_buf *buf,
69
            const struct GUID *client_guid,
70
            const struct smb2_lease_key *lease_key)
71
0
{
72
0
  struct leases_db_key db_key = {
73
0
    .client_guid = *client_guid,
74
0
    .lease_key = *lease_key };
75
0
  DATA_BLOB blob = { .data = buf->buf, .length = sizeof(buf->buf) };
76
0
  enum ndr_err_code ndr_err;
77
78
0
  if (DEBUGLEVEL >= 10) {
79
0
    DBG_DEBUG("\n");
80
0
    NDR_PRINT_DEBUG(leases_db_key, &db_key);
81
0
  }
82
83
0
  ndr_err = ndr_push_struct_into_fixed_blob(
84
0
    &blob, &db_key, (ndr_push_flags_fn_t)ndr_push_leases_db_key);
85
0
  SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
86
87
0
  return (TDB_DATA) { .dptr = buf->buf, .dsize = sizeof(buf->buf) };
88
0
}
89
90
struct leases_db_do_locked_state {
91
  void (*fn)(struct leases_db_value *value,
92
       bool *modified,
93
       void *private_data);
94
  void *private_data;
95
  NTSTATUS status;
96
};
97
98
static void leases_db_do_locked_fn(
99
  struct db_record *rec,
100
  TDB_DATA db_value,
101
  void *private_data)
102
0
{
103
0
  struct leases_db_do_locked_state *state = private_data;
104
0
  DATA_BLOB blob = { .data = db_value.dptr, .length = db_value.dsize };
105
0
  struct leases_db_value *value = NULL;
106
0
  enum ndr_err_code ndr_err;
107
0
  bool modified = false;
108
109
0
  value = talloc_zero(talloc_tos(), struct leases_db_value);
110
0
  if (value == NULL) {
111
0
    state->status = NT_STATUS_NO_MEMORY;
112
0
    goto done;
113
0
  }
114
115
0
  if (blob.length != 0) {
116
0
    ndr_err = ndr_pull_struct_blob_all(
117
0
      &blob,
118
0
      value,
119
0
      value,
120
0
      (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
121
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
122
0
      DBG_ERR("ndr_pull_struct_blob_failed: %s\n",
123
0
          ndr_errstr(ndr_err));
124
0
      state->status = ndr_map_error2ntstatus(ndr_err);
125
0
      goto done;
126
0
    }
127
0
  }
128
129
0
  state->fn(value, &modified, state->private_data);
130
131
0
  if (!modified) {
132
0
    goto done;
133
0
  }
134
135
0
  if (value->num_files == 0) {
136
0
    state->status = dbwrap_record_delete(rec);
137
0
    if (!NT_STATUS_IS_OK(state->status)) {
138
0
      DBG_ERR("dbwrap_record_delete returned %s\n",
139
0
          nt_errstr(state->status));
140
0
    }
141
0
    goto done;
142
0
  }
143
144
0
  ndr_err = ndr_push_struct_blob(
145
0
    &blob,
146
0
    value,
147
0
    value,
148
0
    (ndr_push_flags_fn_t)ndr_push_leases_db_value);
149
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
150
0
    DBG_ERR("ndr_push_struct_blob_failed: %s\n",
151
0
        ndr_errstr(ndr_err));
152
0
    state->status = ndr_map_error2ntstatus(ndr_err);
153
0
    goto done;
154
0
  }
155
156
0
  if (DEBUGLEVEL >= 10) {
157
0
    DBG_DEBUG("\n");
158
0
    NDR_PRINT_DEBUG(leases_db_value, value);
159
0
  }
160
161
0
  db_value = make_tdb_data(blob.data, blob.length);
162
163
0
  state->status = dbwrap_record_store(rec, db_value, 0);
164
0
  if (!NT_STATUS_IS_OK(state->status)) {
165
0
    DBG_ERR("dbwrap_record_store returned %s\n",
166
0
        nt_errstr(state->status));
167
0
  }
168
169
0
done:
170
0
  TALLOC_FREE(value);
171
0
}
172
173
static NTSTATUS leases_db_do_locked(
174
  const struct GUID *client_guid,
175
  const struct smb2_lease_key *lease_key,
176
  void (*fn)(struct leases_db_value *value,
177
       bool *modified,
178
       void *private_data),
179
  void *private_data)
180
0
{
181
0
  struct leases_db_key_buf keybuf;
182
0
  TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
183
0
  struct leases_db_do_locked_state state = {
184
0
    .fn = fn, .private_data = private_data,
185
0
  };
186
0
  NTSTATUS status;
187
188
0
  if (!leases_db_init(false)) {
189
0
    return NT_STATUS_INTERNAL_ERROR;
190
0
  }
191
192
0
  status = dbwrap_do_locked(
193
0
    leases_db, db_key, leases_db_do_locked_fn, &state);
194
0
  if (!NT_STATUS_IS_OK(status)) {
195
0
    return status;
196
0
  }
197
0
  return state.status;
198
0
}
199
200
struct leases_db_add_state {
201
  const struct file_id *id;
202
  uint32_t current_state;
203
  uint16_t lease_version;
204
  uint16_t epoch;
205
  const char *servicepath;
206
  const char *base_name;
207
  const char *stream_name;
208
  NTSTATUS status;
209
};
210
211
static void leases_db_add_fn(
212
  struct leases_db_value *value, bool *modified, void *private_data)
213
0
{
214
0
  struct leases_db_add_state *state = private_data;
215
0
  struct leases_db_file *tmp = NULL;
216
0
  uint32_t i;
217
218
  /* id must be unique. */
219
0
  for (i = 0; i < value->num_files; i++) {
220
0
    if (file_id_equal(state->id, &value->files[i].id)) {
221
0
      state->status = NT_STATUS_OBJECT_NAME_COLLISION;
222
0
      return;
223
0
    }
224
0
  }
225
226
0
  if (value->num_files == 0) {
227
    /* new record */
228
0
    value->current_state = state->current_state;
229
0
    value->lease_version = state->lease_version;
230
0
    value->epoch = state->epoch;
231
0
  }
232
233
0
  tmp = talloc_realloc(
234
0
    value,
235
0
    value->files,
236
0
    struct leases_db_file,
237
0
    value->num_files + 1);
238
0
  if (tmp == NULL) {
239
0
    state->status = NT_STATUS_NO_MEMORY;
240
0
    return;
241
0
  }
242
0
  value->files = tmp;
243
244
0
  value->files[value->num_files] = (struct leases_db_file) {
245
0
    .id = *state->id,
246
0
    .servicepath = state->servicepath,
247
0
    .base_name = state->base_name,
248
0
    .stream_name = state->stream_name,
249
0
  };
250
0
  value->num_files += 1;
251
252
0
  *modified = true;
253
0
}
254
255
NTSTATUS leases_db_add(const struct GUID *client_guid,
256
           const struct smb2_lease_key *lease_key,
257
           const struct file_id *id,
258
           uint32_t current_state,
259
           uint16_t lease_version,
260
           uint16_t epoch,
261
           const char *servicepath,
262
           const char *base_name,
263
           const char *stream_name)
264
0
{
265
0
  struct leases_db_add_state state = {
266
0
    .id = id,
267
0
    .current_state = current_state,
268
0
    .lease_version = lease_version,
269
0
    .epoch = epoch,
270
0
    .servicepath = servicepath,
271
0
    .base_name = base_name,
272
0
    .stream_name = stream_name,
273
0
  };
274
0
  NTSTATUS status;
275
276
0
  status = leases_db_do_locked(
277
0
    client_guid, lease_key, leases_db_add_fn, &state);
278
0
  if (!NT_STATUS_IS_OK(status)) {
279
0
    DBG_DEBUG("leases_db_do_locked failed: %s\n",
280
0
        nt_errstr(status));
281
0
    return status;
282
0
  }
283
0
  return state.status;
284
0
}
285
286
struct leases_db_del_state {
287
  const struct file_id *id;
288
  NTSTATUS status;
289
};
290
291
static void leases_db_del_fn(
292
  struct leases_db_value *value, bool *modified, void *private_data)
293
0
{
294
0
  struct leases_db_del_state *state = private_data;
295
0
  uint32_t i;
296
297
0
  for (i = 0; i < value->num_files; i++) {
298
0
    if (file_id_equal(state->id, &value->files[i].id)) {
299
0
      break;
300
0
    }
301
0
  }
302
0
  if (i == value->num_files) {
303
0
    state->status = NT_STATUS_NOT_FOUND;
304
0
    return;
305
0
  }
306
307
0
  value->files[i] = value->files[value->num_files-1];
308
0
  value->num_files -= 1;
309
310
0
  *modified = true;
311
0
}
312
313
NTSTATUS leases_db_del(const struct GUID *client_guid,
314
           const struct smb2_lease_key *lease_key,
315
           const struct file_id *id)
316
0
{
317
0
  struct leases_db_del_state state = { .id = id };
318
0
  NTSTATUS status;
319
320
0
  status = leases_db_do_locked(
321
0
    client_guid, lease_key, leases_db_del_fn, &state);
322
0
  if (!NT_STATUS_IS_OK(status)) {
323
0
    DBG_DEBUG("leases_db_do_locked failed: %s\n",
324
0
        nt_errstr(status));
325
0
    return status;
326
0
  }
327
0
  return state.status;
328
0
}
329
330
struct leases_db_fetch_state {
331
  void (*parser)(uint32_t num_files,
332
      const struct leases_db_file *files,
333
      void *private_data);
334
  void *private_data;
335
  NTSTATUS status;
336
};
337
338
static void leases_db_parser(TDB_DATA key, TDB_DATA data, void *private_data)
339
0
{
340
0
  struct leases_db_fetch_state *state =
341
0
    (struct leases_db_fetch_state *)private_data;
342
0
  DATA_BLOB blob = { .data = data.dptr, .length = data.dsize };
343
0
  enum ndr_err_code ndr_err;
344
0
  struct leases_db_value *value;
345
346
0
  value = talloc(talloc_tos(), struct leases_db_value);
347
0
  if (value == NULL) {
348
0
    state->status = NT_STATUS_NO_MEMORY;
349
0
    return;
350
0
  }
351
352
0
  ndr_err = ndr_pull_struct_blob_all(
353
0
    &blob, value, value,
354
0
    (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
355
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
356
0
    DEBUG(10, ("%s: ndr_pull_struct_blob_failed: %s\n",
357
0
         __func__, ndr_errstr(ndr_err)));
358
0
    TALLOC_FREE(value);
359
0
    state->status = ndr_map_error2ntstatus(ndr_err);
360
0
    return;
361
0
  }
362
363
0
  if (DEBUGLEVEL >= 10) {
364
0
    DEBUG(10, ("%s:\n", __func__));
365
0
    NDR_PRINT_DEBUG(leases_db_value, value);
366
0
  }
367
368
0
  state->parser(value->num_files,
369
0
      value->files,
370
0
      state->private_data);
371
372
0
  TALLOC_FREE(value);
373
0
  state->status = NT_STATUS_OK;
374
0
}
375
376
NTSTATUS leases_db_parse(const struct GUID *client_guid,
377
       const struct smb2_lease_key *lease_key,
378
       void (*parser)(uint32_t num_files,
379
          const struct leases_db_file *files,
380
          void *private_data),
381
       void *private_data)
382
0
{
383
0
  struct leases_db_key_buf keybuf;
384
0
  TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
385
0
  struct leases_db_fetch_state state;
386
0
  NTSTATUS status;
387
388
0
  if (!leases_db_init(true)) {
389
0
    return NT_STATUS_INTERNAL_ERROR;
390
0
  }
391
392
0
  state = (struct leases_db_fetch_state) {
393
0
    .parser = parser,
394
0
    .private_data = private_data,
395
0
    .status = NT_STATUS_OK
396
0
  };
397
398
0
  status = dbwrap_parse_record(leases_db, db_key, leases_db_parser,
399
0
             &state);
400
0
  if (!NT_STATUS_IS_OK(status)) {
401
0
    return status;
402
0
  }
403
0
  return state.status;
404
0
}
405
406
struct leases_db_rename_state {
407
  const struct file_id *id;
408
  const char *servicename_new;
409
  const char *filename_new;
410
  const char *stream_name_new;
411
  NTSTATUS status;
412
};
413
414
static void leases_db_rename_fn(
415
  struct leases_db_value *value, bool *modified, void *private_data)
416
0
{
417
0
  struct leases_db_rename_state *state = private_data;
418
0
  struct leases_db_file *file = NULL;
419
0
  uint32_t i;
420
421
  /* id must exist. */
422
0
  for (i = 0; i < value->num_files; i++) {
423
0
    if (file_id_equal(state->id, &value->files[i].id)) {
424
0
      break;
425
0
    }
426
0
  }
427
0
  if (i == value->num_files) {
428
0
    state->status = NT_STATUS_NOT_FOUND;
429
0
    return;
430
0
  }
431
432
0
  file = &value->files[i];
433
0
  file->servicepath = state->servicename_new;
434
0
  file->base_name = state->filename_new;
435
0
  file->stream_name = state->stream_name_new;
436
437
0
  *modified = true;
438
0
}
439
440
NTSTATUS leases_db_rename(const struct GUID *client_guid,
441
           const struct smb2_lease_key *lease_key,
442
           const struct file_id *id,
443
           const char *servicename_new,
444
           const char *filename_new,
445
           const char *stream_name_new)
446
0
{
447
0
  struct leases_db_rename_state state = {
448
0
    .id = id,
449
0
    .servicename_new = servicename_new,
450
0
    .filename_new = filename_new,
451
0
    .stream_name_new = stream_name_new,
452
0
  };
453
0
  NTSTATUS status;
454
455
0
  status = leases_db_do_locked(
456
0
    client_guid, lease_key, leases_db_rename_fn, &state);
457
0
  if (!NT_STATUS_IS_OK(status)) {
458
0
    DBG_DEBUG("leases_db_do_locked failed: %s\n",
459
0
        nt_errstr(status));
460
0
    return status;
461
0
  }
462
0
  return state.status;
463
0
}
464
465
struct leases_db_set_state {
466
  uint32_t current_state;
467
  bool breaking;
468
  uint32_t breaking_to_requested;
469
  uint32_t breaking_to_required;
470
  uint16_t lease_version;
471
  uint16_t epoch;
472
};
473
474
static void leases_db_set_fn(
475
  struct leases_db_value *value, bool *modified, void *private_data)
476
0
{
477
0
  struct leases_db_set_state *state = private_data;
478
479
0
  if (value->num_files == 0) {
480
0
    DBG_WARNING("leases_db_set on new entry\n");
481
0
    return;
482
0
  }
483
0
  value->current_state = state->current_state;
484
0
  value->breaking = state->breaking;
485
0
  value->breaking_to_requested = state->breaking_to_requested;
486
0
  value->breaking_to_required = state->breaking_to_required;
487
0
  value->lease_version = state->lease_version;
488
0
  value->epoch = state->epoch;
489
0
  *modified = true;
490
491
0
  if (CHECK_DEBUGLVL(10)) {
492
0
    DBG_DEBUG("\n");
493
0
    NDR_PRINT_DEBUG(leases_db_value, value);
494
0
  }
495
0
}
496
497
NTSTATUS leases_db_set(const struct GUID *client_guid,
498
           const struct smb2_lease_key *lease_key,
499
           uint32_t current_state,
500
           bool breaking,
501
           uint32_t breaking_to_requested,
502
           uint32_t breaking_to_required,
503
           uint16_t lease_version,
504
           uint16_t epoch)
505
0
{
506
0
  struct leases_db_set_state state = {
507
0
    .current_state = current_state,
508
0
    .breaking = breaking,
509
0
    .breaking_to_requested = breaking_to_requested,
510
0
    .breaking_to_required = breaking_to_required,
511
0
    .lease_version = lease_version,
512
0
    .epoch = epoch,
513
0
  };
514
0
  NTSTATUS status;
515
516
0
  status = leases_db_do_locked(
517
0
    client_guid, lease_key, leases_db_set_fn, &state);
518
0
  if (!NT_STATUS_IS_OK(status)) {
519
0
    DBG_DEBUG("leases_db_do_locked failed: %s\n",
520
0
        nt_errstr(status));
521
0
    return status;
522
0
  }
523
0
  return NT_STATUS_OK;
524
0
}
525
526
struct leases_db_get_state {
527
  const struct file_id *file_id;
528
  uint32_t *current_state;
529
  bool *breaking;
530
  uint32_t *breaking_to_requested;
531
  uint32_t *breaking_to_required;
532
  uint16_t *lease_version;
533
  uint16_t *epoch;
534
  NTSTATUS status;
535
};
536
537
static void leases_db_get_fn(TDB_DATA key, TDB_DATA data, void *private_data)
538
0
{
539
0
  struct leases_db_get_state *state = private_data;
540
0
  DATA_BLOB blob = { .data = data.dptr, .length = data.dsize };
541
0
  enum ndr_err_code ndr_err;
542
0
  struct leases_db_value *value;
543
0
  uint32_t i;
544
545
0
  value = talloc(talloc_tos(), struct leases_db_value);
546
0
  if (value == NULL) {
547
0
    state->status = NT_STATUS_NO_MEMORY;
548
0
    return;
549
0
  }
550
551
0
  ndr_err = ndr_pull_struct_blob_all(
552
0
    &blob, value, value,
553
0
    (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
554
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
555
0
    DBG_ERR("ndr_pull_struct_blob_failed: %s\n",
556
0
      ndr_errstr(ndr_err));
557
0
    TALLOC_FREE(value);
558
0
    state->status = ndr_map_error2ntstatus(ndr_err);
559
0
    return;
560
0
  }
561
562
0
  if (DEBUGLEVEL >= 10) {
563
0
    DBG_DEBUG("\n");
564
0
    NDR_PRINT_DEBUG(leases_db_value, value);
565
0
  }
566
567
  /* id must exist. */
568
0
  for (i = 0; i < value->num_files; i++) {
569
0
    if (file_id_equal(state->file_id, &value->files[i].id)) {
570
0
      break;
571
0
    }
572
0
  }
573
574
0
  if (i == value->num_files) {
575
0
    state->status = NT_STATUS_NOT_FOUND;
576
0
    TALLOC_FREE(value);
577
0
    return;
578
0
  }
579
580
0
  if (state->current_state != NULL) {
581
0
    *state->current_state = value->current_state;
582
0
  };
583
0
  if (state->breaking != NULL) {
584
0
    *state->breaking = value->breaking;
585
0
  };
586
0
  if (state->breaking_to_requested != NULL) {
587
0
    *state->breaking_to_requested = value->breaking_to_requested;
588
0
  };
589
0
  if (state->breaking_to_required != NULL) {
590
0
    *state->breaking_to_required = value->breaking_to_required;
591
0
  };
592
0
  if (state->lease_version != NULL) {
593
0
    *state->lease_version = value->lease_version;
594
0
  };
595
0
  if (state->epoch != NULL) {
596
0
    *state->epoch = value->epoch;
597
0
  };
598
599
0
  TALLOC_FREE(value);
600
0
  state->status = NT_STATUS_OK;
601
0
}
602
603
NTSTATUS leases_db_get(const struct GUID *client_guid,
604
           const struct smb2_lease_key *lease_key,
605
           const struct file_id *file_id,
606
           uint32_t *current_state,
607
           bool *breaking,
608
           uint32_t *breaking_to_requested,
609
           uint32_t *breaking_to_required,
610
           uint16_t *lease_version,
611
           uint16_t *epoch)
612
0
{
613
0
  struct leases_db_get_state state = {
614
0
    .file_id = file_id,
615
0
    .current_state = current_state,
616
0
    .breaking = breaking,
617
0
    .breaking_to_requested = breaking_to_requested,
618
0
    .breaking_to_required = breaking_to_required,
619
0
    .lease_version = lease_version,
620
0
    .epoch = epoch,
621
0
  };
622
0
  struct leases_db_key_buf keybuf;
623
0
  TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
624
0
  NTSTATUS status;
625
626
0
  if (!leases_db_init(true)) {
627
0
    return NT_STATUS_INTERNAL_ERROR;
628
0
  }
629
630
0
  status = dbwrap_parse_record(
631
0
    leases_db, db_key, leases_db_get_fn, &state);
632
0
  if (!NT_STATUS_IS_OK(status)) {
633
0
    return status;
634
0
  }
635
0
  return state.status;
636
0
}
637
638
struct leases_db_get_current_state_state {
639
  int seqnum;
640
  uint32_t current_state;
641
  NTSTATUS status;
642
};
643
644
/*
645
 * This function is an optimization that
646
 * relies on the fact that the
647
 * smb2_lease_state current_state
648
 * (which is a uint32_t size)
649
 * from struct leases_db_value is the first
650
 * entry in the ndr-encoded struct leases_db_value.
651
 * Read it without having to ndr decode all
652
 * the values in struct leases_db_value.
653
 */
654
655
static void leases_db_get_current_state_fn(
656
  TDB_DATA key, TDB_DATA data, void *private_data)
657
0
{
658
0
  struct leases_db_get_current_state_state *state = private_data;
659
0
  struct ndr_pull ndr;
660
0
  enum ndr_err_code ndr_err;
661
662
0
  if (data.dsize < sizeof(uint32_t)) {
663
0
    state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
664
0
    return;
665
0
  }
666
667
0
  state->seqnum = dbwrap_get_seqnum(leases_db);
668
669
0
  ndr = (struct ndr_pull) {
670
0
    .data = data.dptr, .data_size = data.dsize,
671
0
  };
672
0
  ndr_err = ndr_pull_uint32(&ndr, NDR_SCALARS, &state->current_state);
673
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
674
0
    state->status = ndr_map_error2ntstatus(ndr_err);
675
0
  }
676
0
}
677
678
NTSTATUS leases_db_get_current_state(
679
  const struct GUID *client_guid,
680
  const struct smb2_lease_key *lease_key,
681
  int *database_seqnum,
682
  uint32_t *current_state)
683
0
{
684
0
  struct leases_db_get_current_state_state state = { 0 };
685
0
  struct leases_db_key_buf keybuf;
686
0
  TDB_DATA db_key = { 0 };
687
0
  NTSTATUS status;
688
689
0
  if (!leases_db_init(true)) {
690
0
    return NT_STATUS_INTERNAL_ERROR;
691
0
  }
692
693
0
  state.seqnum = dbwrap_get_seqnum(leases_db);
694
0
  if (*database_seqnum == state.seqnum) {
695
0
    return NT_STATUS_OK;
696
0
  }
697
698
0
  db_key = leases_db_key(&keybuf, client_guid, lease_key);
699
700
0
  status = dbwrap_parse_record(
701
0
    leases_db, db_key, leases_db_get_current_state_fn, &state);
702
0
  if (!NT_STATUS_IS_OK(status)) {
703
0
    return status;
704
0
  }
705
0
  *database_seqnum = state.seqnum;
706
0
  *current_state = state.current_state;
707
708
0
  return NT_STATUS_OK;
709
0
}
710
711
NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
712
      uint32_t num_files,
713
      const struct leases_db_file *files,
714
      struct file_id **pp_ids)
715
0
{
716
0
  uint32_t i;
717
0
  struct file_id *ids = talloc_array(mem_ctx,
718
0
        struct file_id,
719
0
        num_files);
720
0
  if (ids == NULL) {
721
0
    return NT_STATUS_NO_MEMORY;
722
0
  }
723
724
0
  for (i = 0; i < num_files; i++) {
725
0
    ids[i] = files[i].id;
726
0
  }
727
0
  *pp_ids = ids;
728
0
  return NT_STATUS_OK;
729
0
}