Esempio n. 1
0
/*
  send an oplock break request to a client
*/
NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level)
{
	struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon);
	struct smbsrv_request *req;

	req = smbsrv_init_request(tcon->smb_conn);
	NT_STATUS_HAVE_NO_MEMORY(req);

	smbsrv_setup_reply(req, 8, 0);

	SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
	SSVAL(req->out.hdr,HDR_TID,tcon->tid);
	SSVAL(req->out.hdr,HDR_PID,0xFFFF);
	SSVAL(req->out.hdr,HDR_UID,0);
	SSVAL(req->out.hdr,HDR_MID,0xFFFF);
	SCVAL(req->out.hdr,HDR_FLG,0);
	SSVAL(req->out.hdr,HDR_FLG2,0);

	SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
	SSVAL(req->out.vwv, VWV(1), 0);
	smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs);
	SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
	SCVAL(req->out.vwv, VWV(3)+1, level);
	SIVAL(req->out.vwv, VWV(4), 0);
	SSVAL(req->out.vwv, VWV(6), 0);
	SSVAL(req->out.vwv, VWV(7), 0);

	smbsrv_send_reply(req);
	return NT_STATUS_OK;
}
Esempio n. 2
0
/*
  send a continue request
*/
static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
				 struct smb_trans2 *trans)
{
	struct smbsrv_request *req2;
	struct smbsrv_trans_partial *tp;
	int count;

	/* make sure they don't flood us */
	for (count=0,tp=req->smb_conn->trans_partial;tp;tp=tp->next) count++;
	if (count > 100) {
		smbsrv_send_error(req, NT_STATUS_INSUFFICIENT_RESOURCES);
		return;
	}

	tp = talloc(req, struct smbsrv_trans_partial);

	tp->req = req;
	tp->u.trans = trans;
	tp->command = command;

	DLIST_ADD(req->smb_conn->trans_partial, tp);
	talloc_set_destructor(tp, smbsrv_trans_partial_destructor);

	req2 = smbsrv_setup_secondary_request(req);

	/* send a 'please continue' reply */
	smbsrv_setup_reply(req2, 0, 0);
	smbsrv_send_reply(req2);
}
Esempio n. 3
0
/* 
   construct and send an error packet, then destroy the request 
   auto-converts to DOS error format when appropriate
*/
void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status)
{
	if (req->smb_conn->connection->event.fde == NULL) {
		/* the socket has been destroyed - no point trying to send an error! */
		talloc_free(req);
		return;
	}
	smbsrv_setup_reply(req, 0, 0);

	/* error returns never have any data */
	req_grow_data(req, 0);

	smbsrv_setup_error(req, status);
	smbsrv_send_reply(req);
}
Esempio n. 4
0
/*
  answer a reconstructed trans request
*/
static void reply_trans_send(struct ntvfs_request *ntvfs)
{
	struct smbsrv_request *req;
	struct trans_op *op;
	struct smb_trans2 *trans;
	uint16_t params_left, data_left;
	uint8_t *params, *data;
	int i;

	SMBSRV_CHECK_ASYNC_STATUS_ERR(op, struct trans_op);
	trans = op->trans;

	/* if this function needs work to form the nttrans reply buffer, then
	   call that now */
	if (op->send_fn != NULL) {
		NTSTATUS status;
		status = op->send_fn(op);
		if (!NT_STATUS_IS_OK(status)) {
			smbsrv_send_error(req, status);
			return;
		}
	}

	params_left = trans->out.params.length;
	data_left   = trans->out.data.length;
	params      = trans->out.params.data;
	data        = trans->out.data.data;

	smbsrv_setup_reply(req, 10 + trans->out.setup_count, 0);

	if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) {
		smbsrv_setup_error(req, req->ntvfs->async_states->status);
	}

	/* we need to divide up the reply into chunks that fit into
	   the negotiated buffer size */
	do {
		uint16_t this_data, this_param, max_bytes;
		unsigned int align1 = 1, align2 = (params_left ? 2 : 0);
		struct smbsrv_request *this_req;

		max_bytes = req_max_data(req) - (align1 + align2);

		this_param = params_left;
		if (this_param > max_bytes) {
			this_param = max_bytes;
		}
		max_bytes -= this_param;

		this_data = data_left;
		if (this_data > max_bytes) {
			this_data = max_bytes;
		}

		/* don't destroy unless this is the last chunk */
		if (params_left - this_param != 0 || 
		    data_left - this_data != 0) {
			this_req = smbsrv_setup_secondary_request(req);
		} else {
			this_req = req;
		}

		req_grow_data(this_req, this_param + this_data + (align1 + align2));

		SSVAL(this_req->out.vwv, VWV(0), trans->out.params.length);
		SSVAL(this_req->out.vwv, VWV(1), trans->out.data.length);
		SSVAL(this_req->out.vwv, VWV(2), 0);

		SSVAL(this_req->out.vwv, VWV(3), this_param);
		SSVAL(this_req->out.vwv, VWV(4), align1 + PTR_DIFF(this_req->out.data, this_req->out.hdr));
		SSVAL(this_req->out.vwv, VWV(5), PTR_DIFF(params, trans->out.params.data));

		SSVAL(this_req->out.vwv, VWV(6), this_data);
		SSVAL(this_req->out.vwv, VWV(7), align1 + align2 + 
		      PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr));
		SSVAL(this_req->out.vwv, VWV(8), PTR_DIFF(data, trans->out.data.data));

		SCVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
		SCVAL(this_req->out.vwv, VWV(9)+1, 0); /* reserved */
		for (i=0;i<trans->out.setup_count;i++) {
			SSVAL(this_req->out.vwv, VWV(10+i), trans->out.setup[i]);
		}

		memset(this_req->out.data, 0, align1);
		if (this_param != 0) {
			memcpy(this_req->out.data + align1, params, this_param);
		}
		memset(this_req->out.data+this_param+align1, 0, align2);
		if (this_data != 0) {
			memcpy(this_req->out.data+this_param+align1+align2, data, this_data);
		}

		params_left -= this_param;
		data_left -= this_data;
		params += this_param;
		data += this_data;

		smbsrv_send_reply(this_req);
	} while (params_left != 0 || data_left != 0);
}