3 Unix SMB/Netbios implementation.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1998
9 Copyright (C) John H Terpstra 1995-1998
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 This file handles the named pipe and mailslot calls
27 in the SMBtrans protocol
32 extern int DEBUGLEVEL
;
35 extern fstring local_machine
;
37 #define NERR_notsupported 50
39 extern int smb_read_error
;
41 /*******************************************************************
42 copies parameters and data, as needed, into the smb buffer
44 *both* the data and params sections should be aligned. this
45 is fudged in the rpc pipes by
46 at present, only the data section is. this may be a possible
47 cause of some of the ipc problems being experienced. lkcl26dec97
49 ******************************************************************/
51 static void copy_trans_params_and_data(char *outbuf
, int align
,
52 char *rparam
, int param_offset
, int param_len
,
53 char *rdata
, int data_offset
, int data_len
)
55 char *copy_into
= smb_buf(outbuf
)+1;
63 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
64 param_offset
, param_offset
+ param_len
,
65 data_offset
, data_offset
+ data_len
));
68 memcpy(copy_into
, &rparam
[param_offset
], param_len
);
70 copy_into
+= param_len
+ align
;
73 memcpy(copy_into
, &rdata
[data_offset
], data_len
);
76 /****************************************************************************
78 ****************************************************************************/
80 void send_trans_reply(char *outbuf
,
81 char *rparam
, int rparam_len
,
82 char *rdata
, int rdata_len
,
83 BOOL buffer_too_large
)
85 int this_ldata
,this_lparam
;
86 int tot_data_sent
= 0;
87 int tot_param_sent
= 0;
90 int ldata
= rdata
? rdata_len
: 0;
91 int lparam
= rparam
? rparam_len
: 0;
94 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata
));
96 this_lparam
= MIN(lparam
,max_send
- 500); /* hack */
97 this_ldata
= MIN(ldata
,max_send
- (500+this_lparam
));
99 align
= ((this_lparam
)%4);
101 set_message(outbuf
,10,1+align
+this_ldata
+this_lparam
,True
);
103 if (buffer_too_large
)
105 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
106 SIVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
107 SIVAL(outbuf
, smb_rcls
, 0x80000000 | STATUS_BUFFER_OVERFLOW
);
110 copy_trans_params_and_data(outbuf
, align
,
111 rparam
, tot_param_sent
, this_lparam
,
112 rdata
, tot_data_sent
, this_ldata
);
114 SSVAL(outbuf
,smb_vwv0
,lparam
);
115 SSVAL(outbuf
,smb_vwv1
,ldata
);
116 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
117 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
118 SSVAL(outbuf
,smb_vwv5
,0);
119 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
120 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
121 SSVAL(outbuf
,smb_vwv8
,0);
122 SSVAL(outbuf
,smb_vwv9
,0);
125 send_smb(smbd_server_fd(),outbuf
);
127 tot_data_sent
= this_ldata
;
128 tot_param_sent
= this_lparam
;
130 while (tot_data_sent
< ldata
|| tot_param_sent
< lparam
)
132 this_lparam
= MIN(lparam
-tot_param_sent
, max_send
- 500); /* hack */
133 this_ldata
= MIN(ldata
-tot_data_sent
, max_send
- (500+this_lparam
));
141 align
= (this_lparam
%4);
143 set_message(outbuf
,10,1+this_ldata
+this_lparam
+align
,False
);
145 copy_trans_params_and_data(outbuf
, align
,
146 rparam
, tot_param_sent
, this_lparam
,
147 rdata
, tot_data_sent
, this_ldata
);
149 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
150 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
151 SSVAL(outbuf
,smb_vwv5
,tot_param_sent
);
152 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
153 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
154 SSVAL(outbuf
,smb_vwv8
,tot_data_sent
);
155 SSVAL(outbuf
,smb_vwv9
,0);
158 send_smb(smbd_server_fd(),outbuf
);
160 tot_data_sent
+= this_ldata
;
161 tot_param_sent
+= this_lparam
;
165 /****************************************************************************
166 Start the first part of an RPC reply which began with an SMBtrans request.
167 ****************************************************************************/
169 static BOOL
api_rpc_trans_reply(char *outbuf
, pipes_struct
*p
)
171 char *rdata
= malloc(p
->max_trans_reply
);
175 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
179 if((data_len
= read_from_pipe( p
, rdata
, p
->max_trans_reply
)) < 0) {
184 send_trans_reply(outbuf
, NULL
, 0, rdata
, data_len
, p
->out_data
.current_pdu_len
> data_len
);
190 /****************************************************************************
191 WaitNamedPipeHandleState
192 ****************************************************************************/
194 static BOOL
api_WNPHS(char *outbuf
, pipes_struct
*p
, char *param
, int param_len
)
198 if (!param
|| param_len
< 2)
201 priority
= SVAL(param
,0);
202 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority
));
204 if (wait_rpc_pipe_hnd_state(p
, priority
)) {
205 /* now send the reply */
206 send_trans_reply(outbuf
, NULL
, 0, NULL
, 0, False
);
213 /****************************************************************************
214 SetNamedPipeHandleState
215 ****************************************************************************/
217 static BOOL
api_SNPHS(char *outbuf
, pipes_struct
*p
, char *param
, int param_len
)
221 if (!param
|| param_len
< 2)
225 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id
));
227 if (set_rpc_pipe_hnd_state(p
, id
)) {
228 /* now send the reply */
229 send_trans_reply(outbuf
, NULL
, 0, NULL
, 0, False
);
236 /****************************************************************************
237 When no reply is generated, indicate unsupported.
238 ****************************************************************************/
240 static BOOL
api_no_reply(char *outbuf
, int max_rdata_len
)
245 SSVAL(rparam
,0,NERR_notsupported
);
246 SSVAL(rparam
,2,0); /* converter word */
248 DEBUG(3,("Unsupported API fd command\n"));
250 /* now send the reply */
251 send_trans_reply(outbuf
, rparam
, 4, NULL
, 0, False
);
256 /****************************************************************************
257 Handle remote api calls delivered to a named pipe already opened.
258 ****************************************************************************/
260 static int api_fd_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,
261 uint16
*setup
,char *data
,char *params
,
262 int suwcnt
,int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
265 pipes_struct
*p
= NULL
;
269 DEBUG(5,("api_fd_reply\n"));
271 /* First find out the name of this file. */
273 DEBUG(0,("Unexpected named pipe transaction.\n"));
277 /* Get the file handle and hence the file name. */
279 * NB. The setup array has already been transformed
280 * via SVAL and so is in gost byte order.
282 pnum
= ((int)setup
[1]) & 0xFFFF;
283 subcommand
= ((int)setup
[0]) & 0xFFFF;
285 if(!(p
= get_rpc_pipe(pnum
))) {
286 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum
));
287 return api_no_reply(outbuf
, mdrcnt
);
290 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand
, p
->name
, pnum
));
292 /* record maximum data length that can be transmitted in an SMBtrans */
293 p
->max_trans_reply
= mdrcnt
;
295 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p
, p
->max_trans_reply
));
297 switch (subcommand
) {
299 /* dce/rpc command */
300 reply
= write_to_pipe(p
, data
, tdscnt
);
302 reply
= api_rpc_trans_reply(outbuf
, p
);
305 /* Wait Named Pipe Handle state */
306 reply
= api_WNPHS(outbuf
, p
, params
, tpscnt
);
309 /* Set Named Pipe Handle state */
310 reply
= api_SNPHS(outbuf
, p
, params
, tpscnt
);
315 return api_no_reply(outbuf
, mdrcnt
);
320 /****************************************************************************
321 handle named pipe commands
322 ****************************************************************************/
323 static int named_pipe(connection_struct
*conn
,uint16 vuid
, char *outbuf
,char *name
,
324 uint16
*setup
,char *data
,char *params
,
325 int suwcnt
,int tdscnt
,int tpscnt
,
326 int msrcnt
,int mdrcnt
,int mprcnt
)
328 DEBUG(3,("named pipe command on <%s> name\n", name
));
330 if (strequal(name
,"LANMAN"))
331 return api_reply(conn
,vuid
,outbuf
,data
,params
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
333 if (strequal(name
,"WKSSVC") ||
334 strequal(name
,"SRVSVC") ||
335 strequal(name
,"WINREG") ||
336 strequal(name
,"SAMR") ||
337 strequal(name
,"LSARPC"))
339 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
340 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
343 if (strlen(name
) < 1)
344 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
347 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup
[0],(int)setup
[1]));
353 /****************************************************************************
355 ****************************************************************************/
357 int reply_trans(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int bufsize
)
361 char *data
=NULL
,*params
=NULL
;
364 uint16 vuid
= SVAL(inbuf
,smb_uid
);
365 int tpscnt
= SVAL(inbuf
,smb_vwv0
);
366 int tdscnt
= SVAL(inbuf
,smb_vwv1
);
367 int mprcnt
= SVAL(inbuf
,smb_vwv2
);
368 int mdrcnt
= SVAL(inbuf
,smb_vwv3
);
369 int msrcnt
= CVAL(inbuf
,smb_vwv4
);
370 BOOL close_on_completion
= BITSETW(inbuf
+smb_vwv5
,0);
371 BOOL one_way
= BITSETW(inbuf
+smb_vwv5
,1);
372 int pscnt
= SVAL(inbuf
,smb_vwv9
);
373 int psoff
= SVAL(inbuf
,smb_vwv10
);
374 int dscnt
= SVAL(inbuf
,smb_vwv11
);
375 int dsoff
= SVAL(inbuf
,smb_vwv12
);
376 int suwcnt
= CVAL(inbuf
,smb_vwv13
);
377 START_PROFILE(SMBtrans
);
379 memset(name
, '\0',sizeof(name
));
380 fstrcpy(name
,smb_buf(inbuf
));
382 if (dscnt
> tdscnt
|| pscnt
> tpscnt
) {
383 exit_server("invalid trans parameters\n");
387 if((data
= (char *)malloc(tdscnt
)) == NULL
) {
388 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt
));
389 END_PROFILE(SMBtrans
);
390 return(ERROR(ERRDOS
,ERRnomem
));
392 memcpy(data
,smb_base(inbuf
)+dsoff
,dscnt
);
396 if((params
= (char *)malloc(tpscnt
)) == NULL
) {
397 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt
));
398 END_PROFILE(SMBtrans
);
399 return(ERROR(ERRDOS
,ERRnomem
));
401 memcpy(params
,smb_base(inbuf
)+psoff
,pscnt
);
406 if((setup
= (uint16
*)malloc(suwcnt
*sizeof(uint16
))) == NULL
) {
407 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt
* sizeof(uint16
))));
408 END_PROFILE(SMBtrans
);
409 return(ERROR(ERRDOS
,ERRnomem
));
411 for (i
=0;i
<suwcnt
;i
++)
412 setup
[i
] = SVAL(inbuf
,smb_vwv14
+i
*SIZEOFWORD
);
416 if (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
417 /* We need to send an interim response then receive the rest
418 of the parameter/data bytes */
419 outsize
= set_message(outbuf
,0,0,True
);
421 send_smb(smbd_server_fd(),outbuf
);
424 /* receive the rest of the trans packet */
425 while (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
427 int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
429 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
431 if ((ret
&& (CVAL(inbuf
, smb_com
) != SMBtranss
)) || !ret
) {
433 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
435 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
436 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
444 END_PROFILE(SMBtrans
);
445 return(ERROR(ERRSRV
,ERRerror
));
450 tpscnt
= SVAL(inbuf
,smb_vwv0
);
451 tdscnt
= SVAL(inbuf
,smb_vwv1
);
453 pcnt
= SVAL(inbuf
,smb_vwv2
);
454 poff
= SVAL(inbuf
,smb_vwv3
);
455 pdisp
= SVAL(inbuf
,smb_vwv4
);
457 dcnt
= SVAL(inbuf
,smb_vwv5
);
458 doff
= SVAL(inbuf
,smb_vwv6
);
459 ddisp
= SVAL(inbuf
,smb_vwv7
);
464 if (dscnt
> tdscnt
|| pscnt
> tpscnt
) {
465 exit_server("invalid trans parameters\n");
469 memcpy(params
+pdisp
,smb_base(inbuf
)+poff
,pcnt
);
471 memcpy(data
+ddisp
,smb_base(inbuf
)+doff
,dcnt
);
475 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
476 name
,tdscnt
,tpscnt
,suwcnt
));
479 * WinCE wierdness....
482 if (name
[0] == '\\' && (StrnCaseCmp(&name
[1],local_machine
, strlen(local_machine
)) == 0) &&
483 (name
[strlen(local_machine
)+1] == '\\'))
484 name_offset
= strlen(local_machine
)+1;
486 if (strncmp(&name
[name_offset
],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
487 DEBUG(5,("calling named_pipe\n"));
488 outsize
= named_pipe(conn
,vuid
,outbuf
,
489 name
+name_offset
+strlen("\\PIPE\\"),setup
,data
,params
,
490 suwcnt
,tdscnt
,tpscnt
,msrcnt
,mdrcnt
,mprcnt
);
492 DEBUG(3,("invalid pipe name\n"));
504 if (close_on_completion
)
505 close_cnum(conn
,vuid
);
508 END_PROFILE(SMBtrans
);
513 END_PROFILE(SMBtrans
);
514 return(ERROR(ERRSRV
,ERRnosupport
));
517 END_PROFILE(SMBtrans
);