summaryrefslogtreecommitdiff
path: root/source4/smb_server/trans2.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-29 03:48:49 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:04:58 -0500
commit4676de010f1b1680ce70e2e4ae1eb4af4de26695 (patch)
treed644f08c06d50a5ceb587651e07ed45855ef84ee /source4/smb_server/trans2.c
parentae3b7ef161fcf248f551a2f1ac9d1052f932b3a0 (diff)
downloadsamba-4676de010f1b1680ce70e2e4ae1eb4af4de26695.tar.gz
samba-4676de010f1b1680ce70e2e4ae1eb4af4de26695.tar.bz2
samba-4676de010f1b1680ce70e2e4ae1eb4af4de26695.zip
r3350: fixed a bug with sending multiple replies for the one request, as
happens with trans2, trans and echo. Now that smbd is async we queue the multiples replies all at once, and now need a way to ensure each reply gets it own smbsrv_request buffer. I have added req_setup_secondary() to cope with this. (This used to be commit 2dbd2abc5f197ee21d7dceeda2922c7449c46d99)
Diffstat (limited to 'source4/smb_server/trans2.c')
-rw-r--r--source4/smb_server/trans2.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/source4/smb_server/trans2.c b/source4/smb_server/trans2.c
index ed58791fbe..c5c48d3f64 100644
--- a/source4/smb_server/trans2.c
+++ b/source4/smb_server/trans2.c
@@ -1326,18 +1326,20 @@ void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
params = trans.out.params.data;
data = trans.out.data.data;
+
+ req_setup_reply(req, 10 + trans.out.setup_count, 0);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ req_setup_error(req, 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;
- req_setup_reply(req, 10 + trans.out.setup_count, 0);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_setup_error(req, status);
- }
-
max_bytes = req_max_data(req) - (align1 + align2);
this_param = params_left;
@@ -1351,33 +1353,41 @@ void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
this_data = max_bytes;
}
- req_grow_data(req, this_param + this_data + (align1 + align2));
+ /* don't destroy unless this is the last chunk */
+ if (params_left - this_param != 0 ||
+ data_left - this_data != 0) {
+ this_req = req_setup_secondary(req);
+ } else {
+ this_req = req;
+ }
+
+ req_grow_data(this_req, this_param + this_data + (align1 + align2));
- SSVAL(req->out.vwv, VWV(0), trans.out.params.length);
- SSVAL(req->out.vwv, VWV(1), trans.out.data.length);
- SSVAL(req->out.vwv, VWV(2), 0);
+ 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(req->out.vwv, VWV(3), this_param);
- SSVAL(req->out.vwv, VWV(4), align1 + PTR_DIFF(req->out.data, req->out.hdr));
- SSVAL(req->out.vwv, VWV(5), PTR_DIFF(params, trans.out.params.data));
+ 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(req->out.vwv, VWV(6), this_data);
- SSVAL(req->out.vwv, VWV(7), align1 + align2 +
- PTR_DIFF(req->out.data + this_param, req->out.hdr));
- SSVAL(req->out.vwv, VWV(8), PTR_DIFF(data, trans.out.data.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(req->out.vwv, VWV(9), trans.out.setup_count);
+ SSVAL(this_req->out.vwv, VWV(9), trans.out.setup_count);
for (i=0;i<trans.out.setup_count;i++) {
- SSVAL(req->out.vwv, VWV(10+i), trans.out.setup[i]);
+ SSVAL(this_req->out.vwv, VWV(10+i), trans.out.setup[i]);
}
- memset(req->out.data, 0, align1);
+ memset(this_req->out.data, 0, align1);
if (this_param != 0) {
- memcpy(req->out.data + align1, params, this_param);
+ memcpy(this_req->out.data + align1, params, this_param);
}
- memset(req->out.data+this_param+align1, 0, align2);
+ memset(this_req->out.data+this_param+align1, 0, align2);
if (this_data != 0) {
- memcpy(req->out.data+this_param+align1+align2, data, this_data);
+ memcpy(this_req->out.data+this_param+align1+align2, data, this_data);
}
params_left -= this_param;
@@ -1385,12 +1395,7 @@ void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
params += this_param;
data += this_data;
- /* don't destroy unless this is the last chunk */
- if (params_left != 0 || data_left != 0) {
- talloc_increase_ref_count(req);
- }
-
- req_send_reply(req);
+ req_send_reply(this_req);
} while (params_left != 0 || data_left != 0);
}