2 Unix SMB/Netbios implementation.
4 client transaction calls
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /****************************************************************************
28 send a SMB trans or trans2 request
29 ****************************************************************************/
30 BOOL
cli_send_trans(struct cli_state
*cli
, int trans
,
31 char *name
, int pipe_name_len
,
33 uint16
*setup
, int lsetup
, int msetup
,
34 char *param
, int lparam
, int mparam
,
35 char *data
, int ldata
, int mdata
)
38 int this_ldata
,this_lparam
;
39 int tot_data
=0,tot_param
=0;
40 char *outdata
,*outparam
;
43 this_lparam
= MIN(lparam
,cli
->max_xmit
- (500+lsetup
*2)); /* hack */
44 this_ldata
= MIN(ldata
,cli
->max_xmit
- (500+lsetup
*2+this_lparam
));
46 memset(cli
->outbuf
,'\0',smb_size
);
47 set_message(cli
->outbuf
,14+lsetup
,0,True
);
48 CVAL(cli
->outbuf
,smb_com
) = trans
;
49 SSVAL(cli
->outbuf
,smb_tid
, cli
->cnum
);
50 cli_setup_packet(cli
);
52 outparam
= smb_buf(cli
->outbuf
)+(trans
==SMBtrans
? pipe_name_len
+1 : 3);
53 outdata
= outparam
+this_lparam
;
56 SSVAL(cli
->outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
57 SSVAL(cli
->outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
58 SSVAL(cli
->outbuf
,smb_mprcnt
,mparam
); /* mprcnt */
59 SSVAL(cli
->outbuf
,smb_mdrcnt
,mdata
); /* mdrcnt */
60 SCVAL(cli
->outbuf
,smb_msrcnt
,msetup
); /* msrcnt */
61 SSVAL(cli
->outbuf
,smb_flags
,flags
); /* flags */
62 SIVAL(cli
->outbuf
,smb_timeout
,0); /* timeout */
63 SSVAL(cli
->outbuf
,smb_pscnt
,this_lparam
); /* pscnt */
64 SSVAL(cli
->outbuf
,smb_psoff
,smb_offset(outparam
,cli
->outbuf
)); /* psoff */
65 SSVAL(cli
->outbuf
,smb_dscnt
,this_ldata
); /* dscnt */
66 SSVAL(cli
->outbuf
,smb_dsoff
,smb_offset(outdata
,cli
->outbuf
)); /* dsoff */
67 SCVAL(cli
->outbuf
,smb_suwcnt
,lsetup
); /* suwcnt */
68 for (i
=0;i
<lsetup
;i
++) /* setup[] */
69 SSVAL(cli
->outbuf
,smb_setup
+i
*2,setup
[i
]);
70 p
= smb_buf(cli
->outbuf
);
71 if (trans
==SMBtrans
) {
72 memcpy(p
,name
, pipe_name_len
+ 1); /* name[] */
74 *p
++ = 0; /* put in a null smb_name */
75 *p
++ = 'D'; *p
++ = ' '; /* observed in OS/2 */
77 if (this_lparam
) /* param[] */
78 memcpy(outparam
,param
,this_lparam
);
79 if (this_ldata
) /* data[] */
80 memcpy(outdata
,data
,this_ldata
);
81 set_message(cli
->outbuf
,14+lsetup
, /* wcnt, bcc */
82 PTR_DIFF(outdata
+this_ldata
,smb_buf(cli
->outbuf
)),False
);
84 show_msg(cli
->outbuf
);
87 if (this_ldata
< ldata
|| this_lparam
< lparam
) {
88 /* receive interim response */
89 if (!cli_receive_smb(cli
) ||
90 CVAL(cli
->inbuf
,smb_rcls
) != 0) {
94 tot_data
= this_ldata
;
95 tot_param
= this_lparam
;
97 while (tot_data
< ldata
|| tot_param
< lparam
) {
98 this_lparam
= MIN(lparam
-tot_param
,cli
->max_xmit
- 500); /* hack */
99 this_ldata
= MIN(ldata
-tot_data
,cli
->max_xmit
- (500+this_lparam
));
101 set_message(cli
->outbuf
,trans
==SMBtrans
?8:9,0,True
);
102 CVAL(cli
->outbuf
,smb_com
) = trans
==SMBtrans
? SMBtranss
: SMBtranss2
;
104 outparam
= smb_buf(cli
->outbuf
);
105 outdata
= outparam
+this_lparam
;
107 /* secondary request */
108 SSVAL(cli
->outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
109 SSVAL(cli
->outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
110 SSVAL(cli
->outbuf
,smb_spscnt
,this_lparam
); /* pscnt */
111 SSVAL(cli
->outbuf
,smb_spsoff
,smb_offset(outparam
,cli
->outbuf
)); /* psoff */
112 SSVAL(cli
->outbuf
,smb_spsdisp
,tot_param
); /* psdisp */
113 SSVAL(cli
->outbuf
,smb_sdscnt
,this_ldata
); /* dscnt */
114 SSVAL(cli
->outbuf
,smb_sdsoff
,smb_offset(outdata
,cli
->outbuf
)); /* dsoff */
115 SSVAL(cli
->outbuf
,smb_sdsdisp
,tot_data
); /* dsdisp */
116 if (trans
==SMBtrans2
)
117 SSVALS(cli
->outbuf
,smb_sfid
,fid
); /* fid */
118 if (this_lparam
) /* param[] */
119 memcpy(outparam
,param
+tot_param
,this_lparam
);
120 if (this_ldata
) /* data[] */
121 memcpy(outdata
,data
+tot_data
,this_ldata
);
122 set_message(cli
->outbuf
,trans
==SMBtrans
?8:9, /* wcnt, bcc */
123 PTR_DIFF(outdata
+this_ldata
,smb_buf(cli
->outbuf
)),False
);
125 show_msg(cli
->outbuf
);
128 tot_data
+= this_ldata
;
129 tot_param
+= this_lparam
;
137 /****************************************************************************
138 receive a SMB trans or trans2 response allocating the necessary memory
139 ****************************************************************************/
140 BOOL
cli_receive_trans(struct cli_state
*cli
,int trans
,
141 char **param
, int *param_len
,
142 char **data
, int *data_len
)
146 int this_data
,this_param
;
150 *data_len
= *param_len
= 0;
152 if (!cli_receive_smb(cli
))
155 show_msg(cli
->inbuf
);
158 if (CVAL(cli
->inbuf
,smb_com
) != trans
) {
159 DEBUG(0,("Expected %s response, got command 0x%02x\n",
160 trans
==SMBtrans
?"SMBtrans":"SMBtrans2",
161 CVAL(cli
->inbuf
,smb_com
)));
166 * An NT RPC pipe call can return ERRDOS, ERRmoredata
167 * to a trans call. This is not an error and should not
168 * be treated as such.
171 if (cli_error(cli
, &eclass
, &ecode
, NULL
))
173 if(cli
->nt_pipe_fnum
== 0 || !(eclass
== ERRDOS
&& ecode
== ERRmoredata
))
177 /* parse out the lengths */
178 total_data
= SVAL(cli
->inbuf
,smb_tdrcnt
);
179 total_param
= SVAL(cli
->inbuf
,smb_tprcnt
);
182 *data
= Realloc(*data
,total_data
);
183 *param
= Realloc(*param
,total_param
);
186 this_data
= SVAL(cli
->inbuf
,smb_drcnt
);
187 this_param
= SVAL(cli
->inbuf
,smb_prcnt
);
189 if (this_data
+ *data_len
> total_data
||
190 this_param
+ *param_len
> total_param
) {
191 DEBUG(1,("Data overflow in cli_receive_trans\n"));
196 memcpy(*data
+ SVAL(cli
->inbuf
,smb_drdisp
),
197 smb_base(cli
->inbuf
) + SVAL(cli
->inbuf
,smb_droff
),
200 memcpy(*param
+ SVAL(cli
->inbuf
,smb_prdisp
),
201 smb_base(cli
->inbuf
) + SVAL(cli
->inbuf
,smb_proff
),
203 *data_len
+= this_data
;
204 *param_len
+= this_param
;
206 /* parse out the total lengths again - they can shrink! */
207 total_data
= SVAL(cli
->inbuf
,smb_tdrcnt
);
208 total_param
= SVAL(cli
->inbuf
,smb_tprcnt
);
210 if (total_data
<= *data_len
&& total_param
<= *param_len
)
213 if (!cli_receive_smb(cli
))
216 show_msg(cli
->inbuf
);
219 if (CVAL(cli
->inbuf
,smb_com
) != trans
) {
220 DEBUG(0,("Expected %s response, got command 0x%02x\n",
221 trans
==SMBtrans
?"SMBtrans":"SMBtrans2",
222 CVAL(cli
->inbuf
,smb_com
)));
225 if (cli_error(cli
, &eclass
, &ecode
, NULL
))
227 if(cli
->nt_pipe_fnum
== 0 || !(eclass
== ERRDOS
&& ecode
== ERRmoredata
))