Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/libsmb/clioplock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   Unix SMB/CIFS implementation.
3
   SMB client oplock functions
4
   Copyright (C) Andrew Tridgell 2001
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 "../lib/util/tevent_ntstatus.h"
22
#include "async_smb.h"
23
#include "source3/include/client.h"
24
#include "source3/libsmb/proto.h"
25
#include "../libcli/smb/smbXcli_base.h"
26
27
struct cli_smb_oplock_break_waiter_state {
28
  uint16_t fnum;
29
  uint8_t level;
30
};
31
32
static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq);
33
34
struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx,
35
                struct tevent_context *ev,
36
                struct cli_state *cli)
37
0
{
38
0
  struct tevent_req *req, *subreq;
39
0
  struct cli_smb_oplock_break_waiter_state *state;
40
41
0
  req = tevent_req_create(mem_ctx, &state,
42
0
        struct cli_smb_oplock_break_waiter_state);
43
0
  if (req == NULL) {
44
0
    return NULL;
45
0
  }
46
47
  /*
48
   * Create a fake SMB request that we will never send out. This is only
49
   * used to be set into the pending queue with the right mid.
50
   */
51
0
  subreq = smb1cli_req_create(mem_ctx, ev, cli->conn, 0, 0, 0, 0, 0, 0,
52
0
            0, NULL, NULL, 0, NULL, 0, NULL);
53
0
  if (tevent_req_nomem(subreq, req)) {
54
0
    return tevent_req_post(req, ev);
55
0
  }
56
0
  smb1cli_req_set_mid(subreq, 0xffff);
57
58
0
  if (!smbXcli_req_set_pending(subreq)) {
59
0
    tevent_req_oom(req);
60
0
    return tevent_req_post(req, ev);
61
0
  }
62
0
  tevent_req_set_callback(subreq, cli_smb_oplock_break_waiter_done, req);
63
0
  return req;
64
0
}
65
66
static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq)
67
0
{
68
0
  struct tevent_req *req = tevent_req_callback_data(
69
0
    subreq, struct tevent_req);
70
0
  struct cli_smb_oplock_break_waiter_state *state = tevent_req_data(
71
0
    req, struct cli_smb_oplock_break_waiter_state);
72
0
  struct iovec *iov;
73
0
  uint8_t wct;
74
0
  uint16_t *vwv;
75
0
  NTSTATUS status;
76
77
0
  status = smb1cli_req_recv(subreq, state,
78
0
          &iov, /* piov */
79
0
          NULL, /* phdr */
80
0
          &wct,
81
0
          &vwv,
82
0
          NULL, /* pvwv_offset */
83
0
          NULL, /* pnum_bytes */
84
0
          NULL, /* pbytes */
85
0
          NULL, /* pbytes_offset */
86
0
          NULL, /* pinbuf */
87
0
          NULL, 0); /* expected */
88
0
  TALLOC_FREE(subreq);
89
0
  if (tevent_req_nterror(req, status)) {
90
0
    return;
91
0
  }
92
0
  if (wct < 8) {
93
0
    tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
94
0
    return;
95
0
  }
96
0
  state->fnum = SVAL(vwv+2, 0);
97
0
  state->level = CVAL(vwv+3, 1);
98
0
  tevent_req_done(req);
99
0
}
100
101
NTSTATUS cli_smb_oplock_break_waiter_recv(struct tevent_req *req,
102
            uint16_t *pfnum,
103
            uint8_t *plevel)
104
0
{
105
0
  struct cli_smb_oplock_break_waiter_state *state = tevent_req_data(
106
0
    req, struct cli_smb_oplock_break_waiter_state);
107
0
  NTSTATUS status;
108
109
0
  if (tevent_req_is_nterror(req, &status)) {
110
0
    return status;
111
0
  }
112
0
  *pfnum = state->fnum;
113
0
  *plevel = state->level;
114
0
  return NT_STATUS_OK;
115
0
}
116
117
/****************************************************************************
118
send an ack for an oplock break request
119
****************************************************************************/
120
121
struct cli_oplock_ack_state {
122
  uint8_t dummy;
123
};
124
125
static void cli_oplock_ack_done(struct tevent_req *subreq);
126
127
struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx,
128
               struct tevent_context *ev,
129
               struct cli_state *cli,
130
               uint16_t fnum, uint8_t level)
131
0
{
132
0
  struct tevent_req *req, *subreq;
133
0
  struct cli_oplock_ack_state *state;
134
135
0
  req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);
136
0
  if (req == NULL) {
137
0
    return NULL;
138
0
  }
139
140
0
  subreq = cli_lockingx_send(
141
0
    state,        /* mem_ctx */
142
0
    ev,       /* tevent_context */
143
0
    cli,        /* cli */
144
0
    fnum,       /* fnum */
145
0
    LOCKING_ANDX_OPLOCK_RELEASE, /* typeoflock */
146
0
    level,        /* newoplocklevel */
147
0
    0,        /* timeout */
148
0
    0,        /* num_unlocks */
149
0
    NULL,       /* unlocks */
150
0
    0,        /* num_locks */
151
0
    NULL);        /* locks */
152
153
0
  if (tevent_req_nomem(subreq, req)) {
154
0
    return tevent_req_post(req, ev);
155
0
  }
156
0
  tevent_req_set_callback(subreq, cli_oplock_ack_done, req);
157
0
  return req;
158
0
}
159
160
static void cli_oplock_ack_done(struct tevent_req *subreq)
161
0
{
162
0
  NTSTATUS status = cli_lockingx_recv(subreq);
163
0
  tevent_req_simple_finish_ntstatus(subreq, status);
164
0
}
165
166
NTSTATUS cli_oplock_ack_recv(struct tevent_req *req)
167
0
{
168
0
  return tevent_req_simple_recv_ntstatus(req);
169
0
}
170