[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / smbd / ipc.c
blob6e5ff9f0359a165a8444b20cb9e31d404cc4e215
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(char *outbuf,
76 char *rparam, int rparam_len,
77 char *rdata, int rdata_len,
78 BOOL buffer_too_large)
80 int this_ldata,this_lparam;
81 int tot_data_sent = 0;
82 int tot_param_sent = 0;
83 int align;
85 int ldata = rdata ? rdata_len : 0;
86 int lparam = rparam ? rparam_len : 0;
88 if (buffer_too_large)
89 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
91 this_lparam = MIN(lparam,max_send - 500); /* hack */
92 this_ldata = MIN(ldata,max_send - (500+this_lparam));
94 align = ((this_lparam)%4);
96 if (buffer_too_large) {
97 ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
100 set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
102 copy_trans_params_and_data(outbuf, align,
103 rparam, tot_param_sent, this_lparam,
104 rdata, tot_data_sent, this_ldata);
106 SSVAL(outbuf,smb_vwv0,lparam);
107 SSVAL(outbuf,smb_vwv1,ldata);
108 SSVAL(outbuf,smb_vwv3,this_lparam);
109 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
110 SSVAL(outbuf,smb_vwv5,0);
111 SSVAL(outbuf,smb_vwv6,this_ldata);
112 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
113 SSVAL(outbuf,smb_vwv8,0);
114 SSVAL(outbuf,smb_vwv9,0);
116 show_msg(outbuf);
117 if (!send_smb(smbd_server_fd(),outbuf))
118 exit_server_cleanly("send_trans_reply: send_smb failed.");
120 tot_data_sent = this_ldata;
121 tot_param_sent = this_lparam;
123 while (tot_data_sent < ldata || tot_param_sent < lparam)
125 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
126 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
128 if(this_lparam < 0)
129 this_lparam = 0;
131 if(this_ldata < 0)
132 this_ldata = 0;
134 align = (this_lparam%4);
136 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
138 copy_trans_params_and_data(outbuf, align,
139 rparam, tot_param_sent, this_lparam,
140 rdata, tot_data_sent, this_ldata);
142 SSVAL(outbuf,smb_vwv3,this_lparam);
143 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
144 SSVAL(outbuf,smb_vwv5,tot_param_sent);
145 SSVAL(outbuf,smb_vwv6,this_ldata);
146 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
147 SSVAL(outbuf,smb_vwv8,tot_data_sent);
148 SSVAL(outbuf,smb_vwv9,0);
150 show_msg(outbuf);
151 if (!send_smb(smbd_server_fd(),outbuf))
152 exit_server_cleanly("send_trans_reply: send_smb failed.");
154 tot_data_sent += this_ldata;
155 tot_param_sent += this_lparam;
159 /****************************************************************************
160 Start the first part of an RPC reply which began with an SMBtrans request.
161 ****************************************************************************/
163 static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p)
165 BOOL is_data_outstanding;
166 char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
167 int data_len;
169 if(rdata == NULL) {
170 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
171 return False;
174 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
175 &is_data_outstanding)) < 0) {
176 SAFE_FREE(rdata);
177 return False;
180 send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
182 SAFE_FREE(rdata);
183 return True;
186 /****************************************************************************
187 WaitNamedPipeHandleState
188 ****************************************************************************/
190 static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
192 uint16 priority;
194 if (!param || param_len < 2)
195 return False;
197 priority = SVAL(param,0);
198 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
200 if (wait_rpc_pipe_hnd_state(p, priority)) {
201 /* now send the reply */
202 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
203 return True;
205 return False;
209 /****************************************************************************
210 SetNamedPipeHandleState
211 ****************************************************************************/
213 static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
215 uint16 id;
217 if (!param || param_len < 2)
218 return False;
220 id = SVAL(param,0);
221 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
223 if (set_rpc_pipe_hnd_state(p, id)) {
224 /* now send the reply */
225 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
226 return True;
228 return False;
232 /****************************************************************************
233 When no reply is generated, indicate unsupported.
234 ****************************************************************************/
236 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
238 char rparam[4];
240 /* unsupported */
241 SSVAL(rparam,0,NERR_notsupported);
242 SSVAL(rparam,2,0); /* converter word */
244 DEBUG(3,("Unsupported API fd command\n"));
246 /* now send the reply */
247 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
249 return -1;
252 /****************************************************************************
253 Handle remote api calls delivered to a named pipe already opened.
254 ****************************************************************************/
256 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
257 uint16 *setup,char *data,char *params,
258 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
260 BOOL reply = False;
261 smb_np_struct *p = NULL;
262 int pnum;
263 int subcommand;
265 DEBUG(5,("api_fd_reply\n"));
267 /* First find out the name of this file. */
268 if (suwcnt != 2) {
269 DEBUG(0,("Unexpected named pipe transaction.\n"));
270 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
273 /* Get the file handle and hence the file name. */
275 * NB. The setup array has already been transformed
276 * via SVAL and so is in gost byte order.
278 pnum = ((int)setup[1]) & 0xFFFF;
279 subcommand = ((int)setup[0]) & 0xFFFF;
281 if(!(p = get_rpc_pipe(pnum))) {
282 if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) {
283 /* Win9x does this call with a unicode pipe name, not a pnum. */
284 /* Just return success for now... */
285 DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
286 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
287 return -1;
290 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
291 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
294 if (vuid != p->vuid) {
295 DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %d, "
296 "expected %d\n", pnum, vuid, p->vuid));
297 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
300 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum));
302 /* record maximum data length that can be transmitted in an SMBtrans */
303 p->max_trans_reply = mdrcnt;
305 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
307 switch (subcommand) {
308 case TRANSACT_DCERPCCMD:
309 /* dce/rpc command */
310 reply = write_to_pipe(p, data, tdscnt);
311 if (reply)
312 reply = api_rpc_trans_reply(outbuf, p);
313 break;
314 case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
315 /* Wait Named Pipe Handle state */
316 reply = api_WNPHS(outbuf, p, params, tpscnt);
317 break;
318 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
319 /* Set Named Pipe Handle state */
320 reply = api_SNPHS(outbuf, p, params, tpscnt);
321 break;
322 default:
323 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
326 if (!reply)
327 return api_no_reply(outbuf, mdrcnt);
329 return -1;
332 /****************************************************************************
333 handle named pipe commands
334 ****************************************************************************/
335 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
336 uint16 *setup,char *data,char *params,
337 int suwcnt,int tdscnt,int tpscnt,
338 int msrcnt,int mdrcnt,int mprcnt)
340 DEBUG(3,("named pipe command on <%s> name\n", name));
342 if (strequal(name,"LANMAN"))
343 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
345 if (strequal(name,"WKSSVC") ||
346 strequal(name,"SRVSVC") ||
347 strequal(name,"WINREG") ||
348 strequal(name,"SAMR") ||
349 strequal(name,"LSARPC"))
351 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
352 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
355 if (strlen(name) < 1)
356 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
358 if (setup)
359 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
361 return 0;
364 static NTSTATUS handle_trans(connection_struct *conn,
365 struct trans_state *state,
366 char *outbuf, int *outsize)
368 char *local_machine_name;
369 int name_offset = 0;
371 DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
372 state->name,(unsigned int)state->total_data,(unsigned int)state->total_param,
373 (unsigned int)state->setup_count));
376 * WinCE wierdness....
379 local_machine_name = talloc_asprintf(state, "\\%s\\",
380 get_local_machine_name());
382 if (local_machine_name == NULL) {
383 return NT_STATUS_NO_MEMORY;
386 if (strnequal(state->name, local_machine_name,
387 strlen(local_machine_name))) {
388 name_offset = strlen(local_machine_name)-1;
391 if (!strnequal(&state->name[name_offset], "\\PIPE",
392 strlen("\\PIPE"))) {
393 return NT_STATUS_NOT_SUPPORTED;
396 name_offset += strlen("\\PIPE");
398 /* Win9x weirdness. When talking to a unicode server Win9x
399 only sends \PIPE instead of \PIPE\ */
401 if (state->name[name_offset] == '\\')
402 name_offset++;
404 DEBUG(5,("calling named_pipe\n"));
405 *outsize = named_pipe(conn, state->vuid, outbuf,
406 state->name+name_offset,
407 state->setup,state->data,
408 state->param,
409 state->setup_count,state->total_data,
410 state->total_param,
411 state->max_setup_return,
412 state->max_data_return,
413 state->max_param_return);
415 if (*outsize == 0) {
416 return NT_STATUS_NOT_SUPPORTED;
419 if (state->close_on_completion)
420 close_cnum(conn,state->vuid);
422 return NT_STATUS_OK;
425 /****************************************************************************
426 Reply to a SMBtrans.
427 ****************************************************************************/
429 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
430 int size, int bufsize)
432 int outsize = 0;
433 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
434 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
435 unsigned int psoff = SVAL(inbuf, smb_psoff);
436 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
437 struct trans_state *state;
438 NTSTATUS result;
440 START_PROFILE(SMBtrans);
442 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
443 if (!NT_STATUS_IS_OK(result)) {
444 DEBUG(2, ("Got invalid trans request: %s\n",
445 nt_errstr(result)));
446 END_PROFILE(SMBtrans);
447 return ERROR_NT(result);
450 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
451 DEBUG(0, ("talloc failed\n"));
452 END_PROFILE(SMBtrans);
453 return ERROR_NT(NT_STATUS_NO_MEMORY);
456 state->cmd = SMBtrans;
458 state->mid = SVAL(inbuf, smb_mid);
459 state->vuid = SVAL(inbuf, smb_uid);
460 state->setup_count = CVAL(inbuf, smb_suwcnt);
461 state->setup = NULL;
462 state->total_param = SVAL(inbuf, smb_tpscnt);
463 state->param = NULL;
464 state->total_data = SVAL(inbuf, smb_tdscnt);
465 state->data = NULL;
466 state->max_param_return = SVAL(inbuf, smb_mprcnt);
467 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
468 state->max_setup_return = CVAL(inbuf, smb_msrcnt);
469 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
470 state->one_way = BITSETW(inbuf+smb_vwv5,1);
472 memset(state->name, '\0',sizeof(state->name));
473 srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
474 sizeof(state->name), STR_TERMINATE);
476 if ((dscnt > state->total_data) || (pscnt > state->total_param))
477 goto bad_param;
479 if (state->total_data) {
480 /* Can't use talloc here, the core routines do realloc on the
481 * params and data. Out of paranoia, 100 bytes too many. */
482 state->data = (char *)SMB_MALLOC(state->total_data+100);
483 if (state->data == NULL) {
484 DEBUG(0,("reply_trans: data malloc fail for %u "
485 "bytes !\n", (unsigned int)state->total_data));
486 TALLOC_FREE(state);
487 END_PROFILE(SMBtrans);
488 return(ERROR_DOS(ERRDOS,ERRnomem));
490 /* null-terminate the slack space */
491 memset(&state->data[state->total_data], 0, 100);
492 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
493 goto bad_param;
494 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
495 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
496 goto bad_param;
498 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
501 if (state->total_param) {
502 /* Can't use talloc here, the core routines do realloc on the
503 * params and data. Out of paranoia, 100 bytes too many */
504 state->param = (char *)SMB_MALLOC(state->total_param+100);
505 if (state->param == NULL) {
506 DEBUG(0,("reply_trans: param malloc fail for %u "
507 "bytes !\n", (unsigned int)state->total_param));
508 SAFE_FREE(state->data);
509 TALLOC_FREE(state);
510 END_PROFILE(SMBtrans);
511 return(ERROR_DOS(ERRDOS,ERRnomem));
513 /* null-terminate the slack space */
514 memset(&state->param[state->total_param], 0, 100);
515 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
516 goto bad_param;
517 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
518 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
519 goto bad_param;
521 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
524 state->received_data = dscnt;
525 state->received_param = pscnt;
527 if (state->setup_count) {
528 unsigned int i;
529 if((state->setup = TALLOC_ARRAY(
530 state, uint16, state->setup_count)) == NULL) {
531 DEBUG(0,("reply_trans: setup malloc fail for %u "
532 "bytes !\n", (unsigned int)
533 (state->setup_count * sizeof(uint16))));
534 TALLOC_FREE(state);
535 END_PROFILE(SMBtrans);
536 return(ERROR_DOS(ERRDOS,ERRnomem));
538 if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) >
539 inbuf + size)
540 goto bad_param;
541 if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) ||
542 (smb_vwv14+(state->setup_count*SIZEOFWORD) <
543 (state->setup_count*SIZEOFWORD)))
544 goto bad_param;
546 for (i=0;i<state->setup_count;i++)
547 state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
550 state->received_param = pscnt;
552 if ((state->received_param == state->total_param) &&
553 (state->received_data == state->total_data)) {
555 result = handle_trans(conn, state, outbuf, &outsize);
557 SAFE_FREE(state->data);
558 SAFE_FREE(state->param);
559 TALLOC_FREE(state);
561 if (!NT_STATUS_IS_OK(result)) {
562 END_PROFILE(SMBtrans);
563 return ERROR_NT(result);
566 if (outsize == 0) {
567 END_PROFILE(SMBtrans);
568 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
571 END_PROFILE(SMBtrans);
572 return outsize;
575 DLIST_ADD(conn->pending_trans, state);
577 /* We need to send an interim response then receive the rest
578 of the parameter/data bytes */
579 outsize = set_message(outbuf,0,0,True);
580 show_msg(outbuf);
581 END_PROFILE(SMBtrans);
582 return outsize;
584 bad_param:
586 DEBUG(0,("reply_trans: invalid trans parameters\n"));
587 SAFE_FREE(state->data);
588 SAFE_FREE(state->param);
589 TALLOC_FREE(state);
590 END_PROFILE(SMBtrans);
591 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
594 /****************************************************************************
595 Reply to a secondary SMBtrans.
596 ****************************************************************************/
598 int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
599 int size, int bufsize)
601 int outsize = 0;
602 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
603 struct trans_state *state;
604 NTSTATUS result;
606 START_PROFILE(SMBtranss);
608 show_msg(inbuf);
610 for (state = conn->pending_trans; state != NULL;
611 state = state->next) {
612 if (state->mid == SVAL(inbuf,smb_mid)) {
613 break;
617 if ((state == NULL) || (state->cmd != SMBtrans)) {
618 END_PROFILE(SMBtranss);
619 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
622 /* Revise total_params and total_data in case they have changed
623 * downwards */
625 if (SVAL(inbuf, smb_vwv0) < state->total_param)
626 state->total_param = SVAL(inbuf,smb_vwv0);
627 if (SVAL(inbuf, smb_vwv1) < state->total_data)
628 state->total_data = SVAL(inbuf,smb_vwv1);
630 pcnt = SVAL(inbuf, smb_spscnt);
631 poff = SVAL(inbuf, smb_spsoff);
632 pdisp = SVAL(inbuf, smb_spsdisp);
634 dcnt = SVAL(inbuf, smb_sdscnt);
635 doff = SVAL(inbuf, smb_sdsoff);
636 ddisp = SVAL(inbuf, smb_sdsdisp);
638 state->received_param += pcnt;
639 state->received_data += dcnt;
641 if ((state->received_data > state->total_data) ||
642 (state->received_param > state->total_param))
643 goto bad_param;
645 if (pcnt) {
646 if (pdisp+pcnt > state->total_param)
647 goto bad_param;
648 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
649 goto bad_param;
650 if (pdisp > state->total_param)
651 goto bad_param;
652 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
653 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
654 goto bad_param;
655 if (state->param + pdisp < state->param)
656 goto bad_param;
658 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
659 pcnt);
662 if (dcnt) {
663 if (ddisp+dcnt > state->total_data)
664 goto bad_param;
665 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
666 goto bad_param;
667 if (ddisp > state->total_data)
668 goto bad_param;
669 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
670 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
671 goto bad_param;
672 if (state->data + ddisp < state->data)
673 goto bad_param;
675 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
676 dcnt);
679 if ((state->received_param < state->total_param) ||
680 (state->received_data < state->total_data)) {
681 END_PROFILE(SMBtranss);
682 return -1;
685 /* construct_reply_common has done us the favor to pre-fill the
686 * command field with SMBtranss which is wrong :-)
688 SCVAL(outbuf,smb_com,SMBtrans);
690 result = handle_trans(conn, state, outbuf, &outsize);
692 DLIST_REMOVE(conn->pending_trans, state);
693 SAFE_FREE(state->data);
694 SAFE_FREE(state->param);
695 TALLOC_FREE(state);
697 if ((outsize == 0) || !NT_STATUS_IS_OK(result)) {
698 END_PROFILE(SMBtranss);
699 return(ERROR_DOS(ERRSRV,ERRnosupport));
702 END_PROFILE(SMBtranss);
703 return(outsize);
705 bad_param:
707 DEBUG(0,("reply_transs: invalid trans parameters\n"));
708 DLIST_REMOVE(conn->pending_trans, state);
709 SAFE_FREE(state->data);
710 SAFE_FREE(state->param);
711 TALLOC_FREE(state);
712 END_PROFILE(SMBtranss);
713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);