r22868: Replace some message_send_pid calls with messaging_send_pid calls. More
[Samba/bb.git] / source3 / smbd / ipc.c
blob6b647fc72b665d383bc8cd3e1a335d1506716fa2
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 extern int max_send;
32 #define NERR_notsupported 50
34 extern int smb_read_error;
36 /*******************************************************************
37 copies parameters and data, as needed, into the smb buffer
39 *both* the data and params sections should be aligned. this
40 is fudged in the rpc pipes by
41 at present, only the data section is. this may be a possible
42 cause of some of the ipc problems being experienced. lkcl26dec97
44 ******************************************************************/
46 static void copy_trans_params_and_data(char *outbuf, int align,
47 char *rparam, int param_offset, int param_len,
48 char *rdata, int data_offset, int data_len)
50 char *copy_into = smb_buf(outbuf)+1;
52 if(param_len < 0)
53 param_len = 0;
55 if(data_len < 0)
56 data_len = 0;
58 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
59 param_offset, param_offset + param_len,
60 data_offset , data_offset + data_len));
62 if (param_len)
63 memcpy(copy_into, &rparam[param_offset], param_len);
65 copy_into += param_len + align;
67 if (data_len )
68 memcpy(copy_into, &rdata[data_offset], data_len);
71 /****************************************************************************
72 Send a trans reply.
73 ****************************************************************************/
75 void send_trans_reply(const char *inbuf,
76 char *outbuf,
77 char *rparam,
78 int rparam_len,
79 char *rdata,
80 int rdata_len,
81 BOOL buffer_too_large)
83 int this_ldata,this_lparam;
84 int tot_data_sent = 0;
85 int tot_param_sent = 0;
86 int align;
88 int ldata = rdata ? rdata_len : 0;
89 int lparam = rparam ? rparam_len : 0;
91 if (buffer_too_large)
92 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
94 this_lparam = MIN(lparam,max_send - 500); /* hack */
95 this_ldata = MIN(ldata,max_send - (500+this_lparam));
97 align = ((this_lparam)%4);
99 if (buffer_too_large) {
100 ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
103 set_message(inbuf,outbuf,10,1+align+this_ldata+this_lparam,True);
105 copy_trans_params_and_data(outbuf, align,
106 rparam, tot_param_sent, this_lparam,
107 rdata, tot_data_sent, this_ldata);
109 SSVAL(outbuf,smb_vwv0,lparam);
110 SSVAL(outbuf,smb_vwv1,ldata);
111 SSVAL(outbuf,smb_vwv3,this_lparam);
112 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
113 SSVAL(outbuf,smb_vwv5,0);
114 SSVAL(outbuf,smb_vwv6,this_ldata);
115 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
116 SSVAL(outbuf,smb_vwv8,0);
117 SSVAL(outbuf,smb_vwv9,0);
119 show_msg(outbuf);
120 if (!send_smb(smbd_server_fd(),outbuf))
121 exit_server_cleanly("send_trans_reply: send_smb failed.");
123 tot_data_sent = this_ldata;
124 tot_param_sent = this_lparam;
126 while (tot_data_sent < ldata || tot_param_sent < lparam)
128 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
129 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
131 if(this_lparam < 0)
132 this_lparam = 0;
134 if(this_ldata < 0)
135 this_ldata = 0;
137 align = (this_lparam%4);
139 set_message(inbuf,outbuf,10,1+this_ldata+this_lparam+align,False);
141 copy_trans_params_and_data(outbuf, align,
142 rparam, tot_param_sent, this_lparam,
143 rdata, tot_data_sent, this_ldata);
145 SSVAL(outbuf,smb_vwv3,this_lparam);
146 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
147 SSVAL(outbuf,smb_vwv5,tot_param_sent);
148 SSVAL(outbuf,smb_vwv6,this_ldata);
149 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
150 SSVAL(outbuf,smb_vwv8,tot_data_sent);
151 SSVAL(outbuf,smb_vwv9,0);
153 show_msg(outbuf);
154 if (!send_smb(smbd_server_fd(),outbuf))
155 exit_server_cleanly("send_trans_reply: send_smb failed.");
157 tot_data_sent += this_ldata;
158 tot_param_sent += this_lparam;
162 /****************************************************************************
163 Start the first part of an RPC reply which began with an SMBtrans request.
164 ****************************************************************************/
166 static BOOL api_rpc_trans_reply(const char *inbuf,
167 char *outbuf,
168 smb_np_struct *p)
170 BOOL is_data_outstanding;
171 char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
172 int data_len;
174 if(rdata == NULL) {
175 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
176 return False;
179 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
180 &is_data_outstanding)) < 0) {
181 SAFE_FREE(rdata);
182 return False;
185 send_trans_reply(inbuf, outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
187 SAFE_FREE(rdata);
188 return True;
191 /****************************************************************************
192 WaitNamedPipeHandleState
193 ****************************************************************************/
195 static BOOL api_WNPHS(const char *inbuf,
196 char *outbuf,
197 smb_np_struct *p,
198 char *param,
199 int param_len)
201 uint16 priority;
203 if (!param || param_len < 2)
204 return False;
206 priority = SVAL(param,0);
207 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
209 if (wait_rpc_pipe_hnd_state(p, priority)) {
210 /* now send the reply */
211 send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
212 return True;
214 return False;
218 /****************************************************************************
219 SetNamedPipeHandleState
220 ****************************************************************************/
222 static BOOL api_SNPHS(const char *inbuf,
223 char *outbuf,
224 smb_np_struct *p,
225 char *param,
226 int param_len)
228 uint16 id;
230 if (!param || param_len < 2)
231 return False;
233 id = SVAL(param,0);
234 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
236 if (set_rpc_pipe_hnd_state(p, id)) {
237 /* now send the reply */
238 send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
239 return True;
241 return False;
245 /****************************************************************************
246 When no reply is generated, indicate unsupported.
247 ****************************************************************************/
249 static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len)
251 char rparam[4];
253 /* unsupported */
254 SSVAL(rparam,0,NERR_notsupported);
255 SSVAL(rparam,2,0); /* converter word */
257 DEBUG(3,("Unsupported API fd command\n"));
259 /* now send the reply */
260 send_trans_reply(inbuf, outbuf, rparam, 4, NULL, 0, False);
262 return -1;
265 /****************************************************************************
266 Handle remote api calls delivered to a named pipe already opened.
267 ****************************************************************************/
269 static int api_fd_reply(connection_struct *conn,
270 uint16 vuid,
271 const char *inbuf,
272 char *outbuf,
273 uint16 *setup,
274 char *data,
275 char *params,
276 int suwcnt,
277 int tdscnt,
278 int tpscnt,
279 int mdrcnt,
280 int mprcnt)
282 BOOL reply = False;
283 smb_np_struct *p = NULL;
284 int pnum;
285 int subcommand;
287 DEBUG(5,("api_fd_reply\n"));
289 /* First find out the name of this file. */
290 if (suwcnt != 2) {
291 DEBUG(0,("Unexpected named pipe transaction.\n"));
292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
295 /* Get the file handle and hence the file name. */
297 * NB. The setup array has already been transformed
298 * via SVAL and so is in gost byte order.
300 pnum = ((int)setup[1]) & 0xFFFF;
301 subcommand = ((int)setup[0]) & 0xFFFF;
303 if(!(p = get_rpc_pipe(pnum))) {
304 if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) {
305 /* Win9x does this call with a unicode pipe name, not a pnum. */
306 /* Just return success for now... */
307 DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
308 send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
309 return -1;
312 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
313 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
316 if (vuid != p->vuid) {
317 DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %d, "
318 "expected %d\n", pnum, vuid, p->vuid));
319 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
322 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum));
324 /* record maximum data length that can be transmitted in an SMBtrans */
325 p->max_trans_reply = mdrcnt;
327 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
329 switch (subcommand) {
330 case TRANSACT_DCERPCCMD:
331 /* dce/rpc command */
332 reply = write_to_pipe(p, data, tdscnt);
333 if (reply)
334 reply = api_rpc_trans_reply(inbuf, outbuf, p);
335 break;
336 case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
337 /* Wait Named Pipe Handle state */
338 reply = api_WNPHS(inbuf, outbuf, p, params, tpscnt);
339 break;
340 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
341 /* Set Named Pipe Handle state */
342 reply = api_SNPHS(inbuf, outbuf, p, params, tpscnt);
343 break;
344 default:
345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
348 if (!reply)
349 return api_no_reply(inbuf, outbuf, mdrcnt);
351 return -1;
354 /****************************************************************************
355 Handle named pipe commands.
356 ****************************************************************************/
358 static int named_pipe(connection_struct *conn,
359 uint16 vuid,
360 const char *inbuf,
361 char *outbuf,
362 char *name,
363 uint16 *setup,
364 char *data,
365 char *params,
366 int suwcnt,
367 int tdscnt,
368 int tpscnt,
369 int msrcnt,
370 int mdrcnt,
371 int mprcnt)
373 DEBUG(3,("named pipe command on <%s> name\n", name));
375 if (strequal(name,"LANMAN")) {
376 return api_reply(conn,
377 vuid,
378 inbuf,
379 outbuf,
380 data,
381 params,
382 tdscnt,
383 tpscnt,
384 mdrcnt,
385 mprcnt);
388 if (strequal(name,"WKSSVC") ||
389 strequal(name,"SRVSVC") ||
390 strequal(name,"WINREG") ||
391 strequal(name,"SAMR") ||
392 strequal(name,"LSARPC")) {
393 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
394 return api_fd_reply(conn,
395 vuid,
396 inbuf,
397 outbuf,
398 setup,
399 data,
400 params,
401 suwcnt,
402 tdscnt,
403 tpscnt,
404 mdrcnt,
405 mprcnt);
408 if (strlen(name) < 1) {
409 return api_fd_reply(conn,
410 vuid,
411 inbuf,
412 outbuf,
413 setup,
414 data,
415 params,
416 suwcnt,
417 tdscnt,
418 tpscnt,
419 mdrcnt,
420 mprcnt);
423 if (setup)
424 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
426 return 0;
429 static NTSTATUS handle_trans(connection_struct *conn,
430 struct trans_state *state,
431 const char *inbuf,
432 char *outbuf,
433 int *outsize)
435 char *local_machine_name;
436 int name_offset = 0;
438 DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
439 state->name,(unsigned int)state->total_data,(unsigned int)state->total_param,
440 (unsigned int)state->setup_count));
443 * WinCE wierdness....
446 local_machine_name = talloc_asprintf(state, "\\%s\\",
447 get_local_machine_name());
449 if (local_machine_name == NULL) {
450 return NT_STATUS_NO_MEMORY;
453 if (strnequal(state->name, local_machine_name,
454 strlen(local_machine_name))) {
455 name_offset = strlen(local_machine_name)-1;
458 if (!strnequal(&state->name[name_offset], "\\PIPE",
459 strlen("\\PIPE"))) {
460 return NT_STATUS_NOT_SUPPORTED;
463 name_offset += strlen("\\PIPE");
465 /* Win9x weirdness. When talking to a unicode server Win9x
466 only sends \PIPE instead of \PIPE\ */
468 if (state->name[name_offset] == '\\')
469 name_offset++;
471 DEBUG(5,("calling named_pipe\n"));
472 *outsize = named_pipe(conn,
473 state->vuid,
474 inbuf,
475 outbuf,
476 state->name+name_offset,
477 state->setup,state->data,
478 state->param,
479 state->setup_count,state->total_data,
480 state->total_param,
481 state->max_setup_return,
482 state->max_data_return,
483 state->max_param_return);
485 if (*outsize == 0) {
486 return NT_STATUS_NOT_SUPPORTED;
489 if (state->close_on_completion)
490 close_cnum(conn,state->vuid);
492 return NT_STATUS_OK;
495 /****************************************************************************
496 Reply to a SMBtrans.
497 ****************************************************************************/
499 int reply_trans(connection_struct *conn,
500 char *inbuf,
501 char *outbuf,
502 int size,
503 int bufsize)
505 int outsize = 0;
506 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
507 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
508 unsigned int psoff = SVAL(inbuf, smb_psoff);
509 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
510 struct trans_state *state;
511 NTSTATUS result;
513 START_PROFILE(SMBtrans);
515 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
516 if (!NT_STATUS_IS_OK(result)) {
517 DEBUG(2, ("Got invalid trans request: %s\n",
518 nt_errstr(result)));
519 END_PROFILE(SMBtrans);
520 return ERROR_NT(result);
523 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
524 DEBUG(0, ("talloc failed\n"));
525 END_PROFILE(SMBtrans);
526 return ERROR_NT(NT_STATUS_NO_MEMORY);
529 state->cmd = SMBtrans;
531 state->mid = SVAL(inbuf, smb_mid);
532 state->vuid = SVAL(inbuf, smb_uid);
533 state->setup_count = CVAL(inbuf, smb_suwcnt);
534 state->setup = NULL;
535 state->total_param = SVAL(inbuf, smb_tpscnt);
536 state->param = NULL;
537 state->total_data = SVAL(inbuf, smb_tdscnt);
538 state->data = NULL;
539 state->max_param_return = SVAL(inbuf, smb_mprcnt);
540 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
541 state->max_setup_return = CVAL(inbuf, smb_msrcnt);
542 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
543 state->one_way = BITSETW(inbuf+smb_vwv5,1);
545 memset(state->name, '\0',sizeof(state->name));
546 srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
547 sizeof(state->name), STR_TERMINATE);
549 if ((dscnt > state->total_data) || (pscnt > state->total_param))
550 goto bad_param;
552 if (state->total_data) {
553 /* Can't use talloc here, the core routines do realloc on the
554 * params and data. Out of paranoia, 100 bytes too many. */
555 state->data = (char *)SMB_MALLOC(state->total_data+100);
556 if (state->data == NULL) {
557 DEBUG(0,("reply_trans: data malloc fail for %u "
558 "bytes !\n", (unsigned int)state->total_data));
559 TALLOC_FREE(state);
560 END_PROFILE(SMBtrans);
561 return(ERROR_DOS(ERRDOS,ERRnomem));
563 /* null-terminate the slack space */
564 memset(&state->data[state->total_data], 0, 100);
565 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
566 goto bad_param;
567 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
568 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
569 goto bad_param;
571 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
574 if (state->total_param) {
575 /* Can't use talloc here, the core routines do realloc on the
576 * params and data. Out of paranoia, 100 bytes too many */
577 state->param = (char *)SMB_MALLOC(state->total_param+100);
578 if (state->param == NULL) {
579 DEBUG(0,("reply_trans: param malloc fail for %u "
580 "bytes !\n", (unsigned int)state->total_param));
581 SAFE_FREE(state->data);
582 TALLOC_FREE(state);
583 END_PROFILE(SMBtrans);
584 return(ERROR_DOS(ERRDOS,ERRnomem));
586 /* null-terminate the slack space */
587 memset(&state->param[state->total_param], 0, 100);
588 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
589 goto bad_param;
590 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
591 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
592 goto bad_param;
594 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
597 state->received_data = dscnt;
598 state->received_param = pscnt;
600 if (state->setup_count) {
601 unsigned int i;
602 if((state->setup = TALLOC_ARRAY(
603 state, uint16, state->setup_count)) == NULL) {
604 DEBUG(0,("reply_trans: setup malloc fail for %u "
605 "bytes !\n", (unsigned int)
606 (state->setup_count * sizeof(uint16))));
607 TALLOC_FREE(state);
608 END_PROFILE(SMBtrans);
609 return(ERROR_DOS(ERRDOS,ERRnomem));
611 if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) >
612 inbuf + size)
613 goto bad_param;
614 if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) ||
615 (smb_vwv14+(state->setup_count*SIZEOFWORD) <
616 (state->setup_count*SIZEOFWORD)))
617 goto bad_param;
619 for (i=0;i<state->setup_count;i++)
620 state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
623 state->received_param = pscnt;
625 if ((state->received_param == state->total_param) &&
626 (state->received_data == state->total_data)) {
628 result = handle_trans(conn, state, inbuf, outbuf, &outsize);
630 SAFE_FREE(state->data);
631 SAFE_FREE(state->param);
632 TALLOC_FREE(state);
634 if (!NT_STATUS_IS_OK(result)) {
635 END_PROFILE(SMBtrans);
636 return ERROR_NT(result);
639 if (outsize == 0) {
640 END_PROFILE(SMBtrans);
641 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
644 END_PROFILE(SMBtrans);
645 return outsize;
648 DLIST_ADD(conn->pending_trans, state);
650 /* We need to send an interim response then receive the rest
651 of the parameter/data bytes */
652 outsize = set_message(inbuf,outbuf,0,0,True);
653 show_msg(outbuf);
654 END_PROFILE(SMBtrans);
655 return outsize;
657 bad_param:
659 DEBUG(0,("reply_trans: invalid trans parameters\n"));
660 SAFE_FREE(state->data);
661 SAFE_FREE(state->param);
662 TALLOC_FREE(state);
663 END_PROFILE(SMBtrans);
664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
667 /****************************************************************************
668 Reply to a secondary SMBtrans.
669 ****************************************************************************/
671 int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
672 int size, int bufsize)
674 int outsize = 0;
675 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
676 struct trans_state *state;
677 NTSTATUS result;
679 START_PROFILE(SMBtranss);
681 show_msg(inbuf);
683 for (state = conn->pending_trans; state != NULL;
684 state = state->next) {
685 if (state->mid == SVAL(inbuf,smb_mid)) {
686 break;
690 if ((state == NULL) || (state->cmd != SMBtrans)) {
691 END_PROFILE(SMBtranss);
692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
695 /* Revise total_params and total_data in case they have changed
696 * downwards */
698 if (SVAL(inbuf, smb_vwv0) < state->total_param)
699 state->total_param = SVAL(inbuf,smb_vwv0);
700 if (SVAL(inbuf, smb_vwv1) < state->total_data)
701 state->total_data = SVAL(inbuf,smb_vwv1);
703 pcnt = SVAL(inbuf, smb_spscnt);
704 poff = SVAL(inbuf, smb_spsoff);
705 pdisp = SVAL(inbuf, smb_spsdisp);
707 dcnt = SVAL(inbuf, smb_sdscnt);
708 doff = SVAL(inbuf, smb_sdsoff);
709 ddisp = SVAL(inbuf, smb_sdsdisp);
711 state->received_param += pcnt;
712 state->received_data += dcnt;
714 if ((state->received_data > state->total_data) ||
715 (state->received_param > state->total_param))
716 goto bad_param;
718 if (pcnt) {
719 if (pdisp+pcnt > state->total_param)
720 goto bad_param;
721 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
722 goto bad_param;
723 if (pdisp > state->total_param)
724 goto bad_param;
725 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
726 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
727 goto bad_param;
728 if (state->param + pdisp < state->param)
729 goto bad_param;
731 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
732 pcnt);
735 if (dcnt) {
736 if (ddisp+dcnt > state->total_data)
737 goto bad_param;
738 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
739 goto bad_param;
740 if (ddisp > state->total_data)
741 goto bad_param;
742 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
743 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
744 goto bad_param;
745 if (state->data + ddisp < state->data)
746 goto bad_param;
748 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
749 dcnt);
752 if ((state->received_param < state->total_param) ||
753 (state->received_data < state->total_data)) {
754 END_PROFILE(SMBtranss);
755 return -1;
758 /* construct_reply_common has done us the favor to pre-fill the
759 * command field with SMBtranss which is wrong :-)
761 SCVAL(outbuf,smb_com,SMBtrans);
763 result = handle_trans(conn, state, inbuf, outbuf, &outsize);
765 DLIST_REMOVE(conn->pending_trans, state);
766 SAFE_FREE(state->data);
767 SAFE_FREE(state->param);
768 TALLOC_FREE(state);
770 if ((outsize == 0) || !NT_STATUS_IS_OK(result)) {
771 END_PROFILE(SMBtranss);
772 return(ERROR_DOS(ERRSRV,ERRnosupport));
775 END_PROFILE(SMBtranss);
776 return(outsize);
778 bad_param:
780 DEBUG(0,("reply_transs: invalid trans parameters\n"));
781 DLIST_REMOVE(conn->pending_trans, state);
782 SAFE_FREE(state->data);
783 SAFE_FREE(state->param);
784 TALLOC_FREE(state);
785 END_PROFILE(SMBtranss);
786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);