예제 #1
0
파일: blocking.c 프로젝트: gojdic/samba
static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTATUS status)
{
	/* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to
	   FILE_LOCK_CONFLICT! (tridge) */
	if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
		status = NT_STATUS_FILE_LOCK_CONFLICT;
	}

	if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
		/* Store the last lock error. */
		files_struct *fsp = blr->fsp;

		if (fsp) {
			fsp->last_lock_failure.context.smbpid = blr->lock_pid;
			fsp->last_lock_failure.context.tid = fsp->conn->cnum;
			fsp->last_lock_failure.context.pid = procid_self();
			fsp->last_lock_failure.start = blr->offset;
			fsp->last_lock_failure.size = blr->count;
			fsp->last_lock_failure.fnum = fsp->fnum;
			fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
			fsp->last_lock_failure.lock_flav = blr->lock_flav;
		}
	}

	reply_nterror(blr->req, status);
	if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
			  true, blr->req->seqnum+1,
			  blr->req->encrypted, NULL)) {
		exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
	}
	TALLOC_FREE(blr->req->outbuf);
}
예제 #2
0
파일: blocking.c 프로젝트: gojdic/samba
static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
{
	DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));

	switch(blr->req->cmd) {
	case SMBlockingX:
		reply_lockingX_error(blr, status);
		break;
	case SMBtrans2:
	case SMBtranss2:
		reply_nterror(blr->req, status);

		/*
		 * construct_reply_common has done us the favor to pre-fill
		 * the command field with SMBtranss2 which is wrong :-)
		 */
		SCVAL(blr->req->outbuf,smb_com,SMBtrans2);

		if (!srv_send_smb(smbd_server_fd(),
				  (char *)blr->req->outbuf,
				  true, blr->req->seqnum+1,
				  IS_CONN_ENCRYPTED(blr->fsp->conn),
				  NULL)) {
			exit_server_cleanly("blocking_lock_reply_error: "
					    "srv_send_smb failed.");
		}
		TALLOC_FREE(blr->req->outbuf);
		break;
	default:
		DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
		exit_server("PANIC - unknown type on blocking lock queue");
	}
}
예제 #3
0
파일: blocking.c 프로젝트: AIdrifter/samba
static void reply_lockingX_success(struct blocking_lock_record *blr)
{
	struct smb_request *req = blr->req;

	reply_outbuf(req, 2, 0);
	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */

	/*
	 * As this message is a lockingX call we must handle
	 * any following chained message correctly.
	 * This is normally handled in construct_reply(),
	 * but as that calls switch_message, we can't use
	 * that here and must set up the chain info manually.
	 */

	if (!srv_send_smb(req->sconn,
			(char *)req->outbuf,
			true, req->seqnum+1,
			IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
			&req->pcd)) {
		exit_server_cleanly("construct_reply: srv_send_smb failed.");
	}

	TALLOC_FREE(req->outbuf);
}
예제 #4
0
파일: oplock.c 프로젝트: AIdrifter/samba
static void send_break_message_smb1(files_struct *fsp, int level)
{
	char break_msg[SMB1_BREAK_MESSAGE_LENGTH];

	new_break_message_smb1(fsp, level, break_msg);

	show_msg(break_msg);
	if (!srv_send_smb(fsp->conn->sconn,
			break_msg, false, 0,
			IS_CONN_ENCRYPTED(fsp->conn),
			NULL)) {
		exit_server_cleanly("send_break_message_smb1: "
			"srv_send_smb failed.");
	}
}
예제 #5
0
파일: blocking.c 프로젝트: AIdrifter/samba
static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS status)
{
	DEBUG(10, ("Replying with error=%s. BLR = %p\n", nt_errstr(status), blr));

	switch(blr->req->cmd) {
	case SMBlockingX:
		/*
		 * This code can be called during the rundown of a
		 * file after it was already closed. In that case,
		 * blr->fsp==NULL and we do not need to undo any
		 * locks, they are already gone.
		 */
		if (blr->fsp != NULL) {
			undo_locks_obtained(blr);
		}
		generic_blocking_lock_error(blr, status);
		break;
	case SMBtrans2:
	case SMBtranss2:
		reply_nterror(blr->req, status);

		/*
		 * construct_reply_common has done us the favor to pre-fill
		 * the command field with SMBtranss2 which is wrong :-)
		 */
		SCVAL(blr->req->outbuf,smb_com,SMBtrans2);

		if (!srv_send_smb(blr->req->sconn,
				  (char *)blr->req->outbuf,
				  true, blr->req->seqnum+1,
				  IS_CONN_ENCRYPTED(blr->fsp->conn),
				  NULL)) {
			exit_server_cleanly("blocking_lock_reply_error: "
					    "srv_send_smb failed.");
		}
		TALLOC_FREE(blr->req->outbuf);
		break;
	default:
		DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
		exit_server("PANIC - unknown type on blocking lock queue");
	}
}
예제 #6
0
파일: ipc.c 프로젝트: AIdrifter/samba
void send_trans_reply(connection_struct *conn,
		      struct smb_request *req,
		      char *rparam, int rparam_len,
		      char *rdata, int rdata_len,
		      bool buffer_too_large)
{
	int this_ldata,this_lparam;
	int tot_data_sent = 0;
	int tot_param_sent = 0;
	int align;

	int ldata  = rdata  ? rdata_len : 0;
	int lparam = rparam ? rparam_len : 0;
	struct smbd_server_connection *sconn = req->sconn;
	int max_send = sconn->smb1.sessions.max_send;

	if (buffer_too_large)
		DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));

	this_lparam = MIN(lparam,max_send - 500); /* hack */
	this_ldata  = MIN(ldata,max_send - (500+this_lparam));

	align = ((this_lparam)%4);

	reply_outbuf(req, 10, 1+align+this_ldata+this_lparam);

	/*
	 * We might have SMBtranss in req which was transferred to the outbuf,
	 * fix that.
	 */
	SCVAL(req->outbuf, smb_com, SMBtrans);

	copy_trans_params_and_data((char *)req->outbuf, align,
				rparam, tot_param_sent, this_lparam,
				rdata, tot_data_sent, this_ldata);

	SSVAL(req->outbuf,smb_vwv0,lparam);
	SSVAL(req->outbuf,smb_vwv1,ldata);
	SSVAL(req->outbuf,smb_vwv3,this_lparam);
	SSVAL(req->outbuf,smb_vwv4,
	      smb_offset(smb_buf(req->outbuf)+1, req->outbuf));
	SSVAL(req->outbuf,smb_vwv5,0);
	SSVAL(req->outbuf,smb_vwv6,this_ldata);
	SSVAL(req->outbuf,smb_vwv7,
	      smb_offset(smb_buf(req->outbuf)+1+this_lparam+align,
			 req->outbuf));
	SSVAL(req->outbuf,smb_vwv8,0);
	SSVAL(req->outbuf,smb_vwv9,0);

	if (buffer_too_large) {
		error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata,
				 STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__);
	}

	show_msg((char *)req->outbuf);
	if (!srv_send_smb(sconn, (char *)req->outbuf,
			  true, req->seqnum+1,
			  IS_CONN_ENCRYPTED(conn), &req->pcd)) {
		exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
	}

	TALLOC_FREE(req->outbuf);

	tot_data_sent = this_ldata;
	tot_param_sent = this_lparam;

	while (tot_data_sent < ldata || tot_param_sent < lparam)
	{
		this_lparam = MIN(lparam-tot_param_sent,
				  max_send - 500); /* hack */
		this_ldata  = MIN(ldata -tot_data_sent,
				  max_send - (500+this_lparam));

		if(this_lparam < 0)
			this_lparam = 0;

		if(this_ldata < 0)
			this_ldata = 0;

		align = (this_lparam%4);

		reply_outbuf(req, 10, 1+align+this_ldata+this_lparam);

		/*
		 * We might have SMBtranss in req which was transferred to the
		 * outbuf, fix that.
		 */
		SCVAL(req->outbuf, smb_com, SMBtrans);

		copy_trans_params_and_data((char *)req->outbuf, align,
					   rparam, tot_param_sent, this_lparam,
					   rdata, tot_data_sent, this_ldata);

		SSVAL(req->outbuf,smb_vwv0,lparam);
		SSVAL(req->outbuf,smb_vwv1,ldata);

		SSVAL(req->outbuf,smb_vwv3,this_lparam);
		SSVAL(req->outbuf,smb_vwv4,
		      smb_offset(smb_buf(req->outbuf)+1,req->outbuf));
		SSVAL(req->outbuf,smb_vwv5,tot_param_sent);
		SSVAL(req->outbuf,smb_vwv6,this_ldata);
		SSVAL(req->outbuf,smb_vwv7,
		      smb_offset(smb_buf(req->outbuf)+1+this_lparam+align,
				 req->outbuf));
		SSVAL(req->outbuf,smb_vwv8,tot_data_sent);
		SSVAL(req->outbuf,smb_vwv9,0);

		if (buffer_too_large) {
			error_packet_set((char *)req->outbuf,
					 ERRDOS, ERRmoredata,
					 STATUS_BUFFER_OVERFLOW,
					 __LINE__, __FILE__);
		}

		show_msg((char *)req->outbuf);
		if (!srv_send_smb(sconn, (char *)req->outbuf,
				  true, req->seqnum+1,
				  IS_CONN_ENCRYPTED(conn), &req->pcd))
			exit_server_cleanly("send_trans_reply: srv_send_smb "
					    "failed.");

		tot_data_sent  += this_ldata;
		tot_param_sent += this_lparam;
		TALLOC_FREE(req->outbuf);
	}
}
예제 #7
0
파일: aio.c 프로젝트: rti7743/samba
NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
			      struct smb_request *smbreq,
			      files_struct *fsp, const char *data,
			      SMB_OFF_T startpos,
			      size_t numtowrite)
{
	struct aio_extra *aio_ex;
	SMB_STRUCT_AIOCB *a;
	size_t bufsize;
	size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
	int ret;

	/* Ensure aio is initialized. */
	if (!initialize_async_io_handler()) {
		return NT_STATUS_RETRY;
	}

	if (fsp->base_fsp != NULL) {
		/* No AIO on streams yet */
		DEBUG(10, ("AIO on streams not yet supported\n"));
		return NT_STATUS_RETRY;
	}

	if ((!min_aio_write_size || (numtowrite < min_aio_write_size))
	    && !SMB_VFS_AIO_FORCE(fsp)) {
		/* Too small a write for aio request. */
		DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
			  "small for minimum aio_write of %u\n",
			  (unsigned int)numtowrite,
			  (unsigned int)min_aio_write_size ));
		return NT_STATUS_RETRY;
	}

	/* Only do this on non-chained and non-chaining writes not using the
	 * write cache. */
        if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
		return NT_STATUS_RETRY;
	}

	if (outstanding_aio_calls >= aio_pending_size) {
		DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
			 "activities outstanding.\n",
			  outstanding_aio_calls ));
		DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
			  "aio_write for file %s, offset %.0f, len = %u "
			  "(mid = %u)\n",
			  fsp_str_dbg(fsp), (double)startpos,
			  (unsigned int)numtowrite,
			  (unsigned int)smbreq->mid ));
		return NT_STATUS_RETRY;
	}

	bufsize = smb_size + 6*2;

	if (!(aio_ex = create_aio_extra(NULL, fsp, bufsize))) {
		DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
		return NT_STATUS_NO_MEMORY;
	}
	aio_ex->handle_completion = handle_aio_write_complete;
	aio_ex->write_through = BITSETW(smbreq->vwv+7,0);

	construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
	srv_set_message((char *)aio_ex->outbuf.data, 6, 0, True);
	SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */

	init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
		(uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
		&aio_ex->lock);

	/* Take the lock until the AIO completes. */
	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
		TALLOC_FREE(aio_ex);
		return NT_STATUS_FILE_LOCK_CONFLICT;
	}

	a = &aio_ex->acb;

	/* Now set up the aio record for the write call. */

	a->aio_fildes = fsp->fh->fd;
	a->aio_buf = discard_const_p(char, data);
	a->aio_nbytes = numtowrite;
	a->aio_offset = startpos;
	a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
	a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
	a->aio_sigevent.sigev_value.sival_ptr = aio_ex;

	ret = SMB_VFS_AIO_WRITE(fsp, a);
	if (ret == -1) {
		DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
			 "Error %s\n", strerror(errno) ));
		SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
		TALLOC_FREE(aio_ex);
		return NT_STATUS_RETRY;
	}

	outstanding_aio_calls++;
	aio_ex->smbreq = talloc_move(aio_ex, &smbreq);

	/* This should actually be improved to span the write. */
	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);

	if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
	    && fsp->aio_write_behind) {
		/* Lie to the client and immediately claim we finished the
		 * write. */
	        SSVAL(aio_ex->outbuf.data,smb_vwv2,numtowrite);
                SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
		show_msg((char *)aio_ex->outbuf.data);
		if (!srv_send_smb(aio_ex->smbreq->sconn,
				(char *)aio_ex->outbuf.data,
				true, aio_ex->smbreq->seqnum+1,
				IS_CONN_ENCRYPTED(fsp->conn),
				&aio_ex->smbreq->pcd)) {
			exit_server_cleanly("schedule_aio_write_and_X: "
					    "srv_send_smb failed.");
		}
		DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
			  "behind for file %s\n", fsp_str_dbg(fsp)));
	}