• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/libsmb/
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
22/****************************************************************************
23send an ack for an oplock break request
24****************************************************************************/
25
26struct cli_oplock_ack_state {
27	uint16_t vwv[8];
28};
29
30static void cli_oplock_ack_done(struct tevent_req *subreq);
31
32struct tevent_req *cli_oplock_ack_send(TALLOC_CTX *mem_ctx,
33				       struct tevent_context *ev,
34				       struct cli_state *cli,
35				       uint16_t fnum, uint8_t level)
36{
37	struct tevent_req *req, *subreq;
38	struct cli_oplock_ack_state *state;
39
40	req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);;
41	if (req == NULL) {
42		return NULL;
43	}
44	SCVAL(state->vwv+0, 0, 0xff);
45	SCVAL(state->vwv+0, 1, 0);
46	SSVAL(state->vwv+1, 0, 0);
47	SSVAL(state->vwv+2, 0, fnum);
48	SCVAL(state->vwv+3, 0, LOCKING_ANDX_OPLOCK_RELEASE);
49	SCVAL(state->vwv+3, 1, level);
50	SIVAL(state->vwv+4, 0, 0); /* timeout */
51	SSVAL(state->vwv+6, 0, 0); /* unlockcount */
52	SSVAL(state->vwv+7, 0, 0); /* lockcount */
53
54	subreq = cli_smb_send(state, ev, cli, SMBlockingX, 0, 8, state->vwv,
55			      0, NULL);
56	if (tevent_req_nomem(subreq, req)) {
57		return tevent_req_post(req, ev);
58	}
59	tevent_req_set_callback(subreq, cli_oplock_ack_done, req);
60	return req;
61}
62
63static void cli_oplock_ack_done(struct tevent_req *subreq)
64{
65	struct tevent_req *req = tevent_req_callback_data(
66		subreq, struct tevent_req);
67	NTSTATUS status;
68
69	status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
70	TALLOC_FREE(subreq);
71	if (!NT_STATUS_IS_OK(status)) {
72		tevent_req_nterror(req, status);
73		return;
74	}
75	tevent_req_done(req);
76}
77
78NTSTATUS cli_oplock_ack_recv(struct tevent_req *req)
79{
80	return tevent_req_simple_recv_ntstatus(req);
81}
82
83NTSTATUS cli_oplock_ack(struct cli_state *cli, uint16_t fnum, unsigned char level)
84{
85	TALLOC_CTX *frame = talloc_stackframe();
86	struct event_context *ev;
87	struct tevent_req *req;
88	NTSTATUS status = NT_STATUS_OK;
89
90	if (cli_has_async_calls(cli)) {
91		/*
92		 * Can't use sync call while an async call is in flight
93		 */
94		status = NT_STATUS_INVALID_PARAMETER;
95		goto fail;
96	}
97
98	ev = event_context_init(frame);
99	if (ev == NULL) {
100		status = NT_STATUS_NO_MEMORY;
101		goto fail;
102	}
103
104	req = cli_oplock_ack_send(frame, ev, cli, fnum, level);
105	if (req == NULL) {
106		status = NT_STATUS_NO_MEMORY;
107		goto fail;
108	}
109
110	if (!tevent_req_poll(req, ev)) {
111		status = map_nt_error_from_unix(errno);
112		goto fail;
113	}
114
115	status = cli_oplock_ack_recv(req);
116 fail:
117	TALLOC_FREE(frame);
118	if (!NT_STATUS_IS_OK(status)) {
119		cli_set_error(cli, status);
120	}
121	return status;
122}
123
124/****************************************************************************
125set the oplock handler for a connection
126****************************************************************************/
127
128void cli_oplock_handler(struct cli_state *cli,
129			NTSTATUS (*handler)(struct cli_state *, uint16_t, unsigned char))
130{
131	cli->oplock_handler = handler;
132}
133