uint32_t cli_state_available_size(struct cli_state *cli, uint32_t ofs)
{
	uint32_t ret = smb1cli_conn_max_xmit(cli->conn);

	if (ofs >= ret) {
		return 0;
	}

	ret -= ofs;

	return ret;
}
Beispiel #2
0
static void smb1cli_trans_format(struct smb1cli_trans_state *state,
				 uint8_t *pwct,
				 int *piov_count)
{
	uint8_t wct = 0;
	struct iovec *iov = state->iov;
	uint8_t *pad = state->pad;
	uint16_t *vwv = state->vwv;
	uint32_t param_offset;
	uint32_t this_param = 0;
	uint32_t param_pad;
	uint32_t data_offset;
	uint32_t this_data = 0;
	uint32_t data_pad;
	uint32_t useable_space;
	uint8_t cmd;
	uint32_t max_trans = smb1cli_conn_max_xmit(state->conn);

	cmd = state->cmd;

	if ((state->param_sent != 0) || (state->data_sent != 0)) {
		/* The secondary commands are one after the primary ones */
		cmd += 1;
	}

	param_offset = MIN_SMB_SIZE;

	switch (cmd) {
	case SMBtrans:
		if (smbXcli_conn_use_unicode(state->conn)) {
			pad[0] = 0;
			iov[0].iov_base = (void *)pad;
			iov[0].iov_len = 1;
			param_offset += 1;
			iov += 1;
		}
		iov[0].iov_base = (void *)state->pipe_name_conv;
		iov[0].iov_len = state->pipe_name_conv_len;
		wct = 14 + state->num_setup;
		param_offset += iov[0].iov_len;
		iov += 1;
		break;
	case SMBtrans2:
		pad[0] = 0;
		pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
		pad[2] = ' ';
		iov[0].iov_base = (void *)pad;
		iov[0].iov_len = 3;
		wct = 14 + state->num_setup;
		param_offset += 3;
		iov += 1;
		break;
	case SMBtranss:
		wct = 8;
		break;
	case SMBtranss2:
		wct = 9;
		break;
	case SMBnttrans:
		wct = 19 + state->num_setup;
		break;
	case SMBnttranss:
		wct = 18;
		break;
	}

	param_offset += wct * sizeof(uint16_t);
	useable_space = max_trans - param_offset;

	param_pad = param_offset % 4;
	if (param_pad > 0) {
		param_pad = MIN(param_pad, useable_space);
		iov[0].iov_base = (void *)state->zero_pad;
		iov[0].iov_len = param_pad;
		iov += 1;
		param_offset += param_pad;
	}
	useable_space = max_trans - param_offset;

	if (state->param_sent < state->num_param) {
		this_param = MIN(state->num_param - state->param_sent,
				 useable_space);
		iov[0].iov_base = (void *)(state->param + state->param_sent);
		iov[0].iov_len = this_param;
		iov += 1;
	}

	data_offset = param_offset + this_param;
	useable_space = max_trans - data_offset;

	data_pad = data_offset % 4;
	if (data_pad > 0) {
		data_pad = MIN(data_pad, useable_space);
		iov[0].iov_base = (void *)state->zero_pad;
		iov[0].iov_len = data_pad;
		iov += 1;
		data_offset += data_pad;
	}
	useable_space = max_trans - data_offset;

	if (state->data_sent < state->num_data) {
		this_data = MIN(state->num_data - state->data_sent,
				useable_space);
		iov[0].iov_base = (void *)(state->data + state->data_sent);
		iov[0].iov_len = this_data;
		iov += 1;
	}

	DEBUG(10, ("num_setup=%u, max_setup=%u, "
		   "param_total=%u, this_param=%u, max_param=%u, "
		   "data_total=%u, this_data=%u, max_data=%u, "
		   "param_offset=%u, param_pad=%u, param_disp=%u, "
		   "data_offset=%u, data_pad=%u, data_disp=%u\n",
		   (unsigned)state->num_setup, (unsigned)state->max_setup,
		   (unsigned)state->num_param, (unsigned)this_param,
		   (unsigned)state->rparam.max,
		   (unsigned)state->num_data, (unsigned)this_data,
		   (unsigned)state->rdata.max,
		   (unsigned)param_offset, (unsigned)param_pad,
		   (unsigned)state->param_sent,
		   (unsigned)data_offset, (unsigned)data_pad,
		   (unsigned)state->data_sent));

	switch (cmd) {
	case SMBtrans:
	case SMBtrans2:
		SSVAL(vwv + 0, 0, state->num_param);
		SSVAL(vwv + 1, 0, state->num_data);
		SSVAL(vwv + 2, 0, state->rparam.max);
		SSVAL(vwv + 3, 0, state->rdata.max);
		SCVAL(vwv + 4, 0, state->max_setup);
		SCVAL(vwv + 4, 1, 0);	/* reserved */
		SSVAL(vwv + 5, 0, state->flags);
		SIVAL(vwv + 6, 0, 0);	/* timeout */
		SSVAL(vwv + 8, 0, 0);	/* reserved */
		SSVAL(vwv + 9, 0, this_param);
		SSVAL(vwv +10, 0, param_offset);
		SSVAL(vwv +11, 0, this_data);
		SSVAL(vwv +12, 0, data_offset);
		SCVAL(vwv +13, 0, state->num_setup);
		SCVAL(vwv +13, 1, 0);	/* reserved */
		memcpy(vwv + 14, state->setup,
		       sizeof(uint16_t) * state->num_setup);
		break;
	case SMBtranss:
	case SMBtranss2:
		SSVAL(vwv + 0, 0, state->num_param);
		SSVAL(vwv + 1, 0, state->num_data);
		SSVAL(vwv + 2, 0, this_param);
		SSVAL(vwv + 3, 0, param_offset);
		SSVAL(vwv + 4, 0, state->param_sent);
		SSVAL(vwv + 5, 0, this_data);
		SSVAL(vwv + 6, 0, data_offset);
		SSVAL(vwv + 7, 0, state->data_sent);
		if (cmd == SMBtranss2) {
			SSVAL(vwv + 8, 0, state->fid);
		}
		break;
	case SMBnttrans:
		SCVAL(vwv + 0, 0, state->max_setup);
		SSVAL(vwv + 0, 1, 0); /* reserved */
		SIVAL(vwv + 1, 1, state->num_param);
		SIVAL(vwv + 3, 1, state->num_data);
		SIVAL(vwv + 5, 1, state->rparam.max);
		SIVAL(vwv + 7, 1, state->rdata.max);
		SIVAL(vwv + 9, 1, this_param);
		SIVAL(vwv +11, 1, param_offset);
		SIVAL(vwv +13, 1, this_data);
		SIVAL(vwv +15, 1, data_offset);
		SCVAL(vwv +17, 1, state->num_setup);
		SSVAL(vwv +18, 0, state->function);
		memcpy(vwv + 19, state->setup,
		       sizeof(uint16_t) * state->num_setup);
		break;
	case SMBnttranss:
		SSVAL(vwv + 0, 0, 0); /* reserved */
		SCVAL(vwv + 1, 0, 0); /* reserved */
		SIVAL(vwv + 1, 1, state->num_param);
		SIVAL(vwv + 3, 1, state->num_data);
		SIVAL(vwv + 5, 1, this_param);
		SIVAL(vwv + 7, 1, param_offset);
		SIVAL(vwv + 9, 1, state->param_sent);
		SIVAL(vwv +11, 1, this_data);
		SIVAL(vwv +13, 1, data_offset);
		SIVAL(vwv +15, 1, state->data_sent);
		SCVAL(vwv +17, 1, 0); /* reserved */
		break;
	}

	state->param_sent += this_param;
	state->data_sent += this_data;

	*pwct = wct;
	*piov_count = iov - state->iov;
}