⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trans2.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* make sure we got all the parameters */	if (trans->in.params.length < 12) {		return NT_STATUS_FOOBAR;	}	search = talloc(op, union smb_search_next);	NT_STATUS_HAVE_NO_MEMORY(search);	search->t2fnext.in.handle        = SVAL(trans->in.params.data, 0);	search->t2fnext.in.max_count     = SVAL(trans->in.params.data, 2);	level                            = SVAL(trans->in.params.data, 4);	search->t2fnext.in.resume_key    = IVAL(trans->in.params.data, 6);	search->t2fnext.in.flags         = SVAL(trans->in.params.data, 10);	smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);	if (search->t2fnext.in.last_name == NULL) {		return NT_STATUS_FOOBAR;	}	search->t2fnext.level = RAW_SEARCH_TRANS2;	search->t2fnext.data_level = (enum smb_search_data_level)level;	if (search->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {		return NT_STATUS_INVALID_LEVEL;	}	if (search->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) {		TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,					       &search->t2fnext.in.num_names, 					       &search->t2fnext.in.ea_names));	}	/* setup the private state structure that the backend will give us in the callback */	state = talloc(op, struct find_state);	NT_STATUS_HAVE_NO_MEMORY(state);	state->op		= op;	state->search		= search;	state->data_level	= search->t2fnext.data_level;	state->last_entry_offset= 0;	state->flags		= search->t2fnext.in.flags;	/* setup for just a header in the reply */	TRANS2_CHECK(trans2_setup_reply(trans, 8, 0, 0));	op->op_info = state;	op->send_fn = trans2_findnext_send;	return ntvfs_search_next(req->ntvfs, search, state, find_callback);}/*  backend for trans2 requests*/static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op){	struct smb_trans2 *trans = op->trans;	NTSTATUS status;	/* direct trans2 pass thru */	status = ntvfs_trans2(req->ntvfs, trans);	if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {		return status;	}	/* must have at least one setup word */	if (trans->in.setup_count < 1) {		return NT_STATUS_FOOBAR;	}	/* the trans2 command is in setup[0] */	switch (trans->in.setup[0]) {	case TRANSACT2_FINDFIRST:		return trans2_findfirst(req, op);	case TRANSACT2_FINDNEXT:		return trans2_findnext(req, op);	case TRANSACT2_QPATHINFO:		return trans2_qpathinfo(req, op);	case TRANSACT2_QFILEINFO:		return trans2_qfileinfo(req, op);	case TRANSACT2_SETFILEINFO:		return trans2_setfileinfo(req, op);	case TRANSACT2_SETPATHINFO:		return trans2_setpathinfo(req, op);	case TRANSACT2_QFSINFO:		return trans2_qfsinfo(req, op);	case TRANSACT2_OPEN:		return trans2_open(req, op);	case TRANSACT2_MKDIR:		return trans2_mkdir(req, op);	}	/* an unknown trans2 command */	return NT_STATUS_FOOBAR;}/*  send a continue request*/static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,				 struct smb_trans2 *trans){	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 = talloc_reference(tp, req);	tp->trans = trans;	tp->command = command;	DLIST_ADD(req->smb_conn->trans_partial, tp);	/* send a 'please continue' reply */	smbsrv_setup_reply(req, 0, 0);	smbsrv_send_reply(req);}/*  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;		uint_t 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));		SSVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);		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);}/*  answer a reconstructed trans request*/static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,				 struct smb_trans2 *trans){	struct trans_op *op;	SMBSRV_TALLOC_IO_PTR(op, struct trans_op);	SMBSRV_SETUP_NTVFS_REQUEST(reply_trans_send, NTVFS_ASYNC_STATE_MAY_ASYNC);	op->req		= req;	op->trans	= trans;	op->command	= command;	op->op_info	= NULL;	op->send_fn	= NULL;	/* its a full request, give it to the backend */	if (command == SMBtrans) {		SMBSRV_CALL_NTVFS_BACKEND(ntvfs_trans(req->ntvfs, trans));		return;	} else {		SMBSRV_CALL_NTVFS_BACKEND(trans2_backend(req, op));		return;	}}/*  Reply to an SMBtrans or SMBtrans2 request*/static void reply_trans_generic(struct smbsrv_request *req, uint8_t command){	struct smb_trans2 *trans;	int i;	uint16_t param_ofs, data_ofs;	uint16_t param_count, data_count;	uint16_t param_total, data_total;	/* parse request */	if (req->in.wct < 14) {		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);		return;	}	trans = talloc(req, struct smb_trans2);	if (trans == NULL) {		smbsrv_send_error(req, NT_STATUS_NO_MEMORY);		return;	}	param_total           = SVAL(req->in.vwv, VWV(0));	data_total            = SVAL(req->in.vwv, VWV(1));	trans->in.max_param   = SVAL(req->in.vwv, VWV(2));	trans->in.max_data    = SVAL(req->in.vwv, VWV(3));	trans->in.max_setup   = CVAL(req->in.vwv, VWV(4));	trans->in.flags       = SVAL(req->in.vwv, VWV(5));	trans->in.timeout     = IVAL(req->in.vwv, VWV(6));	param_count           = SVAL(req->in.vwv, VWV(9));	param_ofs             = SVAL(req->in.vwv, VWV(10));	data_count            = SVAL(req->in.vwv, VWV(11));	data_ofs              = SVAL(req->in.vwv, VWV(12));	trans->in.setup_count = CVAL(req->in.vwv, VWV(13));	if (req->in.wct != 14 + trans->in.setup_count) {		smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));		return;	}	/* parse out the setup words */	trans->in.setup = talloc_array(trans, uint16_t, trans->in.setup_count);	if (trans->in.setup_count && !trans->in.setup) {		smbsrv_send_error(req, NT_STATUS_NO_MEMORY);		return;	}	for (i=0;i<trans->in.setup_count;i++) {		trans->in.setup[i] = SVAL(req->in.vwv, VWV(14+i));	}	if (command == SMBtrans) {		req_pull_string(&req->in.bufinfo, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);	}	if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &trans->in.params) ||	    !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &trans->in.data)) {		smbsrv_send_error(req, NT_STATUS_FOOBAR);		return;	}	/* is it a partial request? if so, then send a 'send more' message */	if (param_total > param_count || data_total > data_count) {		reply_trans_continue(req, command, trans);		return;	}	reply_trans_complete(req, command, trans);}/*  Reply to an SMBtranss2 request*/static void reply_transs_generic(struct smbsrv_request *req, uint8_t command){	struct smbsrv_trans_partial *tp;	struct smb_trans2 *trans = NULL;	uint16_t param_ofs, data_ofs;	uint16_t param_count, data_count;	uint16_t param_disp, data_disp;	uint16_t param_total, data_total;	DATA_BLOB params, data;	/* parse request */	if (req->in.wct < 8) {		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);		return;	}	for (tp=req->smb_conn->trans_partial;tp;tp=tp->next) {		if (tp->command == command &&		    SVAL(tp->req->in.hdr, HDR_MID) == SVAL(req->in.hdr, HDR_MID)) {/* TODO: check the VUID, PID and TID too? */			break;		}	}	if (tp == NULL) {		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);		return;	}	trans = tp->trans;	param_total           = SVAL(req->in.vwv, VWV(0));	data_total            = SVAL(req->in.vwv, VWV(1));	param_count           = SVAL(req->in.vwv, VWV(2));	param_ofs             = SVAL(req->in.vwv, VWV(3));	param_disp            = SVAL(req->in.vwv, VWV(4));	data_count            = SVAL(req->in.vwv, VWV(5));	data_ofs              = SVAL(req->in.vwv, VWV(6));	data_disp             = SVAL(req->in.vwv, VWV(7));	if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &params) ||	    !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &data)) {		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);		return;	}	/* only allow contiguous requests */	if ((param_count != 0 &&	     param_disp != trans->in.params.length) ||	    (data_count != 0 && 	     data_disp != trans->in.data.length)) {		smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);		return;			}	/* add to the existing request */	if (param_count != 0) {		trans->in.params.data = talloc_realloc(trans, 							 trans->in.params.data, 							 uint8_t, 							 param_disp + param_count);		if (trans->in.params.data == NULL) {			goto failed;		}		trans->in.params.length = param_disp + param_count;	}	if (data_count != 0) {		trans->in.data.data = talloc_realloc(trans, 						       trans->in.data.data, 						       uint8_t, 						       data_disp + data_count);		if (trans->in.data.data == NULL) {			goto failed;		}		trans->in.data.length = data_disp + data_count;	}	memcpy(trans->in.params.data + param_disp, params.data, params.length);	memcpy(trans->in.data.data + data_disp, data.data, data.length);	/* the sequence number of the reply is taken from the last secondary	   response */	tp->req->seq_num = req->seq_num;	/* we don't reply to Transs2 requests */	talloc_free(req);	if (trans->in.params.length == param_total &&	    trans->in.data.length == data_total) {		/* its now complete */		DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);		reply_trans_complete(tp->req, command, trans);	}	return;failed:		smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);	DLIST_REMOVE(req->smb_conn->trans_partial, tp);	talloc_free(req);	talloc_free(tp);}/*  Reply to an SMBtrans2*/void smbsrv_reply_trans2(struct smbsrv_request *req){	reply_trans_generic(req, SMBtrans2);}/*  Reply to an SMBtrans*/void smbsrv_reply_trans(struct smbsrv_request *req){	reply_trans_generic(req, SMBtrans);}/*  Reply to an SMBtranss request*/void smbsrv_reply_transs(struct smbsrv_request *req){	reply_transs_generic(req, SMBtrans);}/*  Reply to an SMBtranss2 request*/void smbsrv_reply_transs2(struct smbsrv_request *req){	reply_transs_generic(req, SMBtrans2);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -