Commit an updated configure, but the build_farm should run autoconf!
[Samba.git] / source3 / smbd / ipc.c
blobe853112bfee173304a0956ef2e99150cac6ba4cc
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 SMB Version handling
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
29 #include "includes.h"
31 extern int DEBUGLEVEL;
32 extern int max_send;
34 extern fstring local_machine;
36 #define NERR_notsupported 50
38 extern int smb_read_error;
39 extern uint32 global_client_caps;
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;
57 if(param_len < 0)
58 param_len = 0;
60 if(data_len < 0)
61 data_len = 0;
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));
67 if (param_len)
68 memcpy(copy_into, &rparam[param_offset], param_len);
70 copy_into += param_len + align;
72 if (data_len )
73 memcpy(copy_into, &rdata[data_offset], data_len);
76 /****************************************************************************
77 Send a trans reply.
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;
88 int align;
90 int ldata = rdata ? rdata_len : 0;
91 int lparam = rparam ? rparam_len : 0;
93 if (buffer_too_large)
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 if (!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32 ))) {
107 /* Win9x version. */
108 SSVAL(outbuf, smb_err, ERRmoredata);
109 SCVAL(outbuf, smb_rcls, ERRDOS);
110 } else {
111 SIVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
112 SIVAL(outbuf, smb_rcls, 0x80000000 | STATUS_BUFFER_OVERFLOW);
116 copy_trans_params_and_data(outbuf, align,
117 rparam, tot_param_sent, this_lparam,
118 rdata, tot_data_sent, this_ldata);
120 SSVAL(outbuf,smb_vwv0,lparam);
121 SSVAL(outbuf,smb_vwv1,ldata);
122 SSVAL(outbuf,smb_vwv3,this_lparam);
123 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
124 SSVAL(outbuf,smb_vwv5,0);
125 SSVAL(outbuf,smb_vwv6,this_ldata);
126 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
127 SSVAL(outbuf,smb_vwv8,0);
128 SSVAL(outbuf,smb_vwv9,0);
130 show_msg(outbuf);
131 if (!send_smb(smbd_server_fd(),outbuf))
132 exit_server("send_trans_reply: send_smb failed.\n");
134 tot_data_sent = this_ldata;
135 tot_param_sent = this_lparam;
137 while (tot_data_sent < ldata || tot_param_sent < lparam)
139 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
140 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
142 if(this_lparam < 0)
143 this_lparam = 0;
145 if(this_ldata < 0)
146 this_ldata = 0;
148 align = (this_lparam%4);
150 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
152 copy_trans_params_and_data(outbuf, align,
153 rparam, tot_param_sent, this_lparam,
154 rdata, tot_data_sent, this_ldata);
156 SSVAL(outbuf,smb_vwv3,this_lparam);
157 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
158 SSVAL(outbuf,smb_vwv5,tot_param_sent);
159 SSVAL(outbuf,smb_vwv6,this_ldata);
160 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
161 SSVAL(outbuf,smb_vwv8,tot_data_sent);
162 SSVAL(outbuf,smb_vwv9,0);
164 show_msg(outbuf);
165 if (!send_smb(smbd_server_fd(),outbuf))
166 exit_server("send_trans_reply: send_smb failed.\n");
168 tot_data_sent += this_ldata;
169 tot_param_sent += this_lparam;
173 /****************************************************************************
174 Start the first part of an RPC reply which began with an SMBtrans request.
175 ****************************************************************************/
177 static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
179 char *rdata = malloc(p->max_trans_reply);
180 int data_len;
182 if(rdata == NULL) {
183 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
184 return False;
187 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) {
188 free(rdata);
189 return False;
192 send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len);
194 free(rdata);
195 return True;
198 /****************************************************************************
199 WaitNamedPipeHandleState
200 ****************************************************************************/
202 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
204 uint16 priority;
206 if (!param || param_len < 2)
207 return False;
209 priority = SVAL(param,0);
210 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
212 if (wait_rpc_pipe_hnd_state(p, priority)) {
213 /* now send the reply */
214 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
215 return True;
217 return False;
221 /****************************************************************************
222 SetNamedPipeHandleState
223 ****************************************************************************/
225 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
227 uint16 id;
229 if (!param || param_len < 2)
230 return False;
232 id = SVAL(param,0);
233 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
235 if (set_rpc_pipe_hnd_state(p, id)) {
236 /* now send the reply */
237 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
238 return True;
240 return False;
244 /****************************************************************************
245 When no reply is generated, indicate unsupported.
246 ****************************************************************************/
248 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
250 char rparam[4];
252 /* unsupported */
253 SSVAL(rparam,0,NERR_notsupported);
254 SSVAL(rparam,2,0); /* converter word */
256 DEBUG(3,("Unsupported API fd command\n"));
258 /* now send the reply */
259 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
261 return -1;
264 /****************************************************************************
265 Handle remote api calls delivered to a named pipe already opened.
266 ****************************************************************************/
268 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
269 uint16 *setup,char *data,char *params,
270 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
272 BOOL reply = False;
273 pipes_struct *p = NULL;
274 int pnum;
275 int subcommand;
277 DEBUG(5,("api_fd_reply\n"));
279 /* First find out the name of this file. */
280 if (suwcnt != 2) {
281 DEBUG(0,("Unexpected named pipe transaction.\n"));
282 return(-1);
285 /* Get the file handle and hence the file name. */
287 * NB. The setup array has already been transformed
288 * via SVAL and so is in gost byte order.
290 pnum = ((int)setup[1]) & 0xFFFF;
291 subcommand = ((int)setup[0]) & 0xFFFF;
293 if(!(p = get_rpc_pipe(pnum))) {
294 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
295 return api_no_reply(outbuf, mdrcnt);
298 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
300 /* record maximum data length that can be transmitted in an SMBtrans */
301 p->max_trans_reply = mdrcnt;
303 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
305 switch (subcommand) {
306 case 0x26:
307 /* dce/rpc command */
308 reply = write_to_pipe(p, data, tdscnt);
309 if (reply)
310 reply = api_rpc_trans_reply(outbuf, p);
311 break;
312 case 0x53:
313 /* Wait Named Pipe Handle state */
314 reply = api_WNPHS(outbuf, p, params, tpscnt);
315 break;
316 case 0x01:
317 /* Set Named Pipe Handle state */
318 reply = api_SNPHS(outbuf, p, params, tpscnt);
319 break;
322 if (!reply)
323 return api_no_reply(outbuf, mdrcnt);
325 return -1;
328 /****************************************************************************
329 handle named pipe commands
330 ****************************************************************************/
331 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
332 uint16 *setup,char *data,char *params,
333 int suwcnt,int tdscnt,int tpscnt,
334 int msrcnt,int mdrcnt,int mprcnt)
336 DEBUG(3,("named pipe command on <%s> name\n", name));
338 if (strequal(name,"LANMAN"))
339 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
341 if (strequal(name,"WKSSVC") ||
342 strequal(name,"SRVSVC") ||
343 strequal(name,"WINREG") ||
344 strequal(name,"SAMR") ||
345 strequal(name,"LSARPC"))
347 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
348 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
351 if (strlen(name) < 1)
352 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
354 if (setup)
355 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
357 return 0;
361 /****************************************************************************
362 Reply to a SMBtrans.
363 ****************************************************************************/
365 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
367 fstring name;
368 int name_offset = 0;
369 char *data=NULL,*params=NULL;
370 uint16 *setup=NULL;
371 int outsize = 0;
372 uint16 vuid = SVAL(inbuf,smb_uid);
373 int tpscnt = SVAL(inbuf,smb_vwv0);
374 int tdscnt = SVAL(inbuf,smb_vwv1);
375 int mprcnt = SVAL(inbuf,smb_vwv2);
376 int mdrcnt = SVAL(inbuf,smb_vwv3);
377 int msrcnt = CVAL(inbuf,smb_vwv4);
378 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
379 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
380 int pscnt = SVAL(inbuf,smb_vwv9);
381 int psoff = SVAL(inbuf,smb_vwv10);
382 int dscnt = SVAL(inbuf,smb_vwv11);
383 int dsoff = SVAL(inbuf,smb_vwv12);
384 int suwcnt = CVAL(inbuf,smb_vwv13);
385 START_PROFILE(SMBtrans);
387 memset(name, '\0',sizeof(name));
388 srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE);
390 if (dscnt > tdscnt || pscnt > tpscnt) {
391 exit_server("invalid trans parameters\n");
394 if (tdscnt) {
395 if((data = (char *)malloc(tdscnt)) == NULL) {
396 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
397 END_PROFILE(SMBtrans);
398 return(ERROR(ERRDOS,ERRnomem));
400 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
403 if (tpscnt) {
404 if((params = (char *)malloc(tpscnt)) == NULL) {
405 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
406 END_PROFILE(SMBtrans);
407 return(ERROR(ERRDOS,ERRnomem));
409 memcpy(params,smb_base(inbuf)+psoff,pscnt);
412 if (suwcnt) {
413 int i;
414 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
415 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
416 END_PROFILE(SMBtrans);
417 return(ERROR(ERRDOS,ERRnomem));
419 for (i=0;i<suwcnt;i++)
420 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
424 if (pscnt < tpscnt || dscnt < tdscnt) {
425 /* We need to send an interim response then receive the rest
426 of the parameter/data bytes */
427 outsize = set_message(outbuf,0,0,True);
428 show_msg(outbuf);
429 if (!send_smb(smbd_server_fd(),outbuf))
430 exit_server("reply_trans: send_smb failed.\n");
433 /* receive the rest of the trans packet */
434 while (pscnt < tpscnt || dscnt < tdscnt) {
435 BOOL ret;
436 int pcnt,poff,dcnt,doff,pdisp,ddisp;
438 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
440 if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
441 if(ret) {
442 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
443 } else {
444 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
445 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
447 if (params)
448 free(params);
449 if (data)
450 free(data);
451 if (setup)
452 free(setup);
453 END_PROFILE(SMBtrans);
454 return(ERROR(ERRSRV,ERRerror));
457 show_msg(inbuf);
459 tpscnt = SVAL(inbuf,smb_vwv0);
460 tdscnt = SVAL(inbuf,smb_vwv1);
462 pcnt = SVAL(inbuf,smb_vwv2);
463 poff = SVAL(inbuf,smb_vwv3);
464 pdisp = SVAL(inbuf,smb_vwv4);
466 dcnt = SVAL(inbuf,smb_vwv5);
467 doff = SVAL(inbuf,smb_vwv6);
468 ddisp = SVAL(inbuf,smb_vwv7);
470 pscnt += pcnt;
471 dscnt += dcnt;
473 if (dscnt > tdscnt || pscnt > tpscnt) {
474 exit_server("invalid trans parameters\n");
477 if (pcnt)
478 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
479 if (dcnt)
480 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
484 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
485 name,tdscnt,tpscnt,suwcnt));
488 * WinCE wierdness....
491 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) &&
492 (name[strlen(local_machine)+1] == '\\'))
493 name_offset = strlen(local_machine)+1;
495 if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) {
496 name_offset += strlen("\\PIPE");
498 /* Win9x weirdness. When talking to a unicode server Win9x
499 only sends \PIPE instead of \PIPE\ */
501 if (name[name_offset] == '\\')
502 name_offset++;
504 DEBUG(5,("calling named_pipe\n"));
505 outsize = named_pipe(conn,vuid,outbuf,
506 name+name_offset,setup,data,params,
507 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
508 } else {
509 DEBUG(3,("invalid pipe name\n"));
510 outsize = 0;
514 if (data)
515 free(data);
516 if (params)
517 free(params);
518 if (setup)
519 free(setup);
521 if (close_on_completion)
522 close_cnum(conn,vuid);
524 if (one_way) {
525 END_PROFILE(SMBtrans);
526 return(-1);
529 if (outsize == 0) {
530 END_PROFILE(SMBtrans);
531 return(ERROR(ERRSRV,ERRnosupport));
534 END_PROFILE(SMBtrans);
535 return(outsize);