3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1998,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8 * Copyright (C) Jeremy Allison 1999.
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.
29 #define PIPE "\\PIPE\\"
30 #define PIPELEN strlen(PIPE)
32 extern int DEBUGLEVEL;
33 static pipes_struct *chain_p;
34 static int pipes_open;
36 #ifndef MAX_OPEN_PIPES
37 #define MAX_OPEN_PIPES 64
40 static pipes_struct *Pipes;
41 static struct bitmap *bmap;
43 /* this must be larger than the sum of the open files and directories */
44 static int pipe_handle_offset;
46 /****************************************************************************
47 Set the pipe_handle_offset. Called from smbd/files.c
48 ****************************************************************************/
50 void set_pipe_handle_offset(int max_open_files)
52 if(max_open_files < 0x7000)
53 pipe_handle_offset = 0x7000;
55 pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
58 /****************************************************************************
59 Reset pipe chain handle number.
60 ****************************************************************************/
61 void reset_chain_p(void)
66 /****************************************************************************
67 Initialise pipe handle states.
68 ****************************************************************************/
70 void init_rpc_pipe_hnd(void)
72 bmap = bitmap_allocate(MAX_OPEN_PIPES);
74 exit_server("out of memory in init_rpc_pipe_hnd\n");
77 /****************************************************************************
78 Initialise an outgoing packet.
79 ****************************************************************************/
81 static BOOL pipe_init_outgoing_data(pipes_struct *p)
83 output_data *o_data = &p->out_data;
85 /* Reset the offset counters. */
86 o_data->data_sent_length = 0;
87 o_data->current_pdu_len = 0;
88 o_data->current_pdu_sent = 0;
90 memset(o_data->current_pdu, '\0', sizeof(o_data->current_pdu));
92 /* Free any memory in the current return data buffer. */
93 prs_mem_free(&o_data->rdata);
96 * Initialize the outgoing RPC data buffer.
97 * we will use this as the raw data area for replying to rpc requests.
99 if(!prs_init(&o_data->rdata, MAX_PDU_FRAG_LEN, 4, p->mem_ctx, MARSHALL)) {
100 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
107 /****************************************************************************
108 Find first available pipe slot.
109 ****************************************************************************/
111 pipes_struct *open_rpc_pipe_p(char *pipe_name,
112 connection_struct *conn, uint16 vuid)
116 static int next_pipe;
118 DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
119 pipe_name, pipes_open));
122 /* not repeating pipe numbers makes it easier to track things in
123 log files and prevents client bugs where pipe numbers are reused
124 over connection restarts */
126 next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
128 i = bitmap_find(bmap, next_pipe);
131 DEBUG(0,("ERROR! Out of pipe structures\n"));
135 next_pipe = (i+1) % MAX_OPEN_PIPES;
137 for (p = Pipes; p; p = p->next)
138 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
140 p = (pipes_struct *)malloc(sizeof(*p));
147 if ((p->mem_ctx = talloc_init()) == NULL) {
148 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
156 * Initialize the incoming RPC data buffer with one PDU worth of memory.
157 * We cheat here and say we're marshalling, as we intend to add incoming
158 * data directly into the prs_struct and we want it to auto grow. We will
159 * change the type to UNMARSALLING before processing the stream.
162 if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, 4, p->mem_ctx, MARSHALL)) {
163 DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
168 i += pipe_handle_offset;
180 p->max_trans_reply = 0;
182 p->ntlmssp_chal_flags = 0;
183 p->ntlmssp_auth_validated = False;
184 p->ntlmssp_auth_requested = False;
186 p->pipe_bound = False;
187 p->fault_state = False;
190 * Initialize the incoming RPC struct.
193 p->in_data.pdu_needed_len = 0;
194 p->in_data.pdu_received_len = 0;
197 * Initialize the outgoing RPC struct.
200 p->out_data.current_pdu_len = 0;
201 p->out_data.current_pdu_sent = 0;
202 p->out_data.data_sent_length = 0;
205 * Initialize the outgoing RPC data buffer with no memory.
207 prs_init(&p->out_data.rdata, 0, 4, p->mem_ctx, MARSHALL);
209 ZERO_STRUCT(p->pipe_user);
211 p->pipe_user.uid = (uid_t)-1;
212 p->pipe_user.gid = (gid_t)-1;
214 fstrcpy(p->name, pipe_name);
216 DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
217 pipe_name, i, pipes_open));
221 /* OVERWRITE p as a temp variable, to display all open pipes */
222 for (p = Pipes; p; p = p->next)
223 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
228 /****************************************************************************
229 Sets the fault state on incoming packets.
230 ****************************************************************************/
232 static void set_incoming_fault(pipes_struct *p)
234 prs_mem_free(&p->in_data.data);
235 p->in_data.pdu_needed_len = 0;
236 p->in_data.pdu_received_len = 0;
237 p->fault_state = True;
238 DEBUG(10,("set_incoming_fault: Setting fault state on pipe %s : pnum = 0x%x\n",
242 /****************************************************************************
243 Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
244 ****************************************************************************/
246 static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
248 size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
250 DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
251 (unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
252 (unsigned int)p->in_data.pdu_received_len ));
254 memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
255 p->in_data.pdu_received_len += len_needed_to_complete_hdr;
257 return (ssize_t)len_needed_to_complete_hdr;
260 /****************************************************************************
261 Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
262 ****************************************************************************/
264 static ssize_t unmarshall_rpc_header(pipes_struct *p)
267 * Unmarshall the header to determine the needed length.
272 if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
273 DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
274 set_incoming_fault(p);
278 prs_init( &rpc_in, 0, 4, p->mem_ctx, UNMARSHALL);
279 prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
280 p->in_data.pdu_received_len, False);
283 * Unmarshall the header as this will tell us how much
284 * data we need to read to get the complete pdu.
287 if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
288 DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
289 set_incoming_fault(p);
290 prs_mem_free(&rpc_in);
295 * Validate the RPC header.
298 if(p->hdr.major != 5 && p->hdr.minor != 0) {
299 DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
300 set_incoming_fault(p);
301 prs_mem_free(&rpc_in);
306 * If there is no data in the incoming buffer and it's a requst pdu then
307 * ensure that the FIRST flag is set. If not then we have
308 * a stream missmatch.
311 if((p->hdr.pkt_type == RPC_REQUEST) && (prs_offset(&p->in_data.data) == 0) && !(p->hdr.flags & RPC_FLG_FIRST)) {
312 DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
313 set_incoming_fault(p);
314 prs_mem_free(&rpc_in);
319 * Ensure that the pdu length is sane.
322 if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > MAX_PDU_FRAG_LEN)) {
323 DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
324 set_incoming_fault(p);
325 prs_mem_free(&rpc_in);
329 DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
330 (unsigned int)p->hdr.flags ));
333 * Adjust for the header we just ate.
335 p->in_data.pdu_received_len = 0;
336 p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
339 * Null the data we just ate.
342 memset((char *)&p->in_data.current_in_pdu[0], '\0', RPC_HEADER_LEN);
344 prs_mem_free(&rpc_in);
346 return 0; /* No extra data processed. */
349 /****************************************************************************
350 Processes a request pdu. This will do auth processing if needed, and
351 appends the data into the complete stream if the LAST flag is not set.
352 ****************************************************************************/
354 static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
356 BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
357 size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
358 (auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
361 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
362 set_incoming_fault(p);
367 * Check if we need to do authentication processing.
368 * This is only done on requests, not binds.
372 * Read the RPC request header.
375 if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
376 DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
377 set_incoming_fault(p);
381 if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) {
382 DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
383 set_incoming_fault(p);
387 if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) {
390 * Authentication _was_ requested and it already failed.
393 DEBUG(0,("process_request_pdu: RPC request received on pipe %s where \
394 authentication failed. Denying the request.\n", p->name));
395 set_incoming_fault(p);
400 * Check the data length doesn't go over the 10Mb limit.
403 if(prs_data_size(&p->in_data.data) + data_len > 10*1024*1024) {
404 DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
405 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
406 set_incoming_fault(p);
411 * Append the data portion into the buffer and return.
415 char *data_from = prs_data_p(rpc_in_p) + prs_offset(rpc_in_p);
417 if(!prs_append_data(&p->in_data.data, data_from, data_len)) {
418 DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
419 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
420 set_incoming_fault(p);
426 if(p->hdr.flags & RPC_FLG_LAST) {
429 * Ok - we finally have a complete RPC stream.
430 * Call the rpc command to process it.
434 * Ensure the internal prs buffer size is *exactly* the same
435 * size as the current offset.
438 if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data)))
440 DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
441 set_incoming_fault(p);
446 * Set the parse offset to the start of the data and set the
447 * prs_struct to UNMARSHALL.
450 prs_set_offset(&p->in_data.data, 0);
451 prs_switch_type(&p->in_data.data, UNMARSHALL);
454 * Process the complete data stream here.
457 if(pipe_init_outgoing_data(p))
458 ret = api_pipe_request(p);
461 * We have consumed the whole data stream. Set back to
462 * marshalling and set the offset back to the start of
463 * the buffer to re-use it (we could also do a prs_mem_free()
464 * and then re_init on the next start of PDU. Not sure which
465 * is best here.... JRA.
468 prs_switch_type(&p->in_data.data, MARSHALL);
469 prs_set_offset(&p->in_data.data, 0);
476 /****************************************************************************
477 Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
478 already been parsed and stored in p->hdr.
479 ****************************************************************************/
481 static ssize_t process_complete_pdu(pipes_struct *p)
484 size_t data_len = p->in_data.pdu_received_len;
485 char *data_p = (char *)&p->in_data.current_in_pdu[0];
489 DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
491 set_incoming_fault(p);
493 return (ssize_t)data_len;
496 prs_init( &rpc_in, 0, 4, p->mem_ctx, UNMARSHALL);
497 prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
499 DEBUG(10,("process_complete_pdu: processing packet type %u\n",
500 (unsigned int)p->hdr.pkt_type ));
502 switch (p->hdr.pkt_type) {
506 * We assume that a pipe bind is only in one pdu.
508 if(pipe_init_outgoing_data(p))
509 reply = api_pipe_bind_req(p, &rpc_in);
513 * We assume that a pipe bind_resp is only in one pdu.
515 if(pipe_init_outgoing_data(p))
516 reply = api_pipe_bind_auth_resp(p, &rpc_in);
519 reply = process_request_pdu(p, &rpc_in);
522 DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
527 DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));
528 set_incoming_fault(p);
530 prs_mem_free(&rpc_in);
533 * Reset the lengths. We're ready for a new pdu.
535 p->in_data.pdu_needed_len = 0;
536 p->in_data.pdu_received_len = 0;
539 prs_mem_free(&rpc_in);
540 return (ssize_t)data_len;
543 /****************************************************************************
544 Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
545 ****************************************************************************/
547 static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
549 size_t data_to_copy = MIN(n, MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
551 DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
552 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
555 if(data_to_copy == 0) {
557 * This is an error - data is being received and there is no
558 * space in the PDU. Free the received data and go into the fault state.
560 DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
561 incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
562 set_incoming_fault(p);
567 * If we have no data already, wait until we get at least a RPC_HEADER_LEN
568 * number of bytes before we can do anything.
571 if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
573 * Always return here. If we have more data then the RPC_HEADER
574 * will be processed the next time around the loop.
576 return fill_rpc_header(p, data, data_to_copy);
580 * At this point we know we have at least an RPC_HEADER_LEN amount of data
581 * stored in current_in_pdu.
585 * If pdu_needed_len is zero this is a new pdu.
586 * Unmarshall the header so we know how much more
587 * data we need, then loop again.
590 if(p->in_data.pdu_needed_len == 0)
591 return unmarshall_rpc_header(p);
594 * Ok - at this point we have a valid RPC_HEADER in p->hdr.
595 * Keep reading until we have a full pdu.
598 data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
601 * Copy as much of the data as we need into the current_in_pdu buffer.
604 memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
605 p->in_data.pdu_received_len += data_to_copy;
608 * Do we have a complete PDU ?
611 if(p->in_data.pdu_received_len == p->in_data.pdu_needed_len)
612 return process_complete_pdu(p);
614 DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
615 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
617 return (ssize_t)data_to_copy;
621 /****************************************************************************
622 Accepts incoming data on an rpc pipe.
623 ****************************************************************************/
625 ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n)
627 size_t data_left = n;
629 DEBUG(6,("write_to_pipe: %x", p->pnum));
631 DEBUG(6,(" name: %s open: %s len: %d\n",
632 p->name, BOOLSTR(p->open), (int)n));
634 dump_data(50, data, n);
639 DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
641 data_used = process_incoming_data(p, data, data_left);
643 DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
648 data_left -= data_used;
655 /****************************************************************************
656 Replies to a request to read data from a pipe.
658 Headers are interspersed with the data at PDU intervals. By the time
659 this function is called, the start of the data could possibly have been
660 read by an SMBtrans (file_offset != 0).
662 Calling create_rpc_reply() here is a hack. The data should already
663 have been prepared into arrays of headers + data stream sections.
664 ****************************************************************************/
666 ssize_t read_from_pipe(pipes_struct *p, char *data, size_t n)
668 uint32 pdu_remaining = 0;
669 ssize_t data_returned = 0;
671 if (!p || !p->open) {
672 DEBUG(0,("read_from_pipe: pipe not open\n"));
676 DEBUG(6,("read_from_pipe: %x", p->pnum));
678 DEBUG(6,(" name: %s len: %u\n", p->name, (unsigned int)n));
681 * We cannot return more than one PDU length per
685 if(n > MAX_PDU_FRAG_LEN) {
686 DEBUG(0,("read_from_pipe: loo large read (%u) requested on pipe %s. We can \
687 only service %d sized reads.\n", (unsigned int)n, p->name, MAX_PDU_FRAG_LEN ));
692 * Determine if there is still data to send in the
693 * pipe PDU buffer. Always send this first. Never
694 * send more than is left in the current PDU. The
695 * client should send a new read request for a new
699 if((pdu_remaining = p->out_data.current_pdu_len - p->out_data.current_pdu_sent) > 0) {
700 data_returned = (ssize_t)MIN(n, pdu_remaining);
702 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \
703 returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len,
704 (unsigned int)p->out_data.current_pdu_sent, (int)data_returned));
706 memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned);
707 p->out_data.current_pdu_sent += (uint32)data_returned;
712 * At this point p->current_pdu_len == p->current_pdu_sent (which
713 * may of course be zero if this is the first return fragment.
716 DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \
717 = %u, prs_offset(&p->out_data.rdata) = %u.\n",
718 p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) ));
720 if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
722 * We have sent all possible data, return 0.
729 * We need to create a new PDU from the data left in p->rdata.
730 * Create the header/data/footers. This also sets up the fields
731 * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
732 * and stores the outgoing PDU in p->current_pdu.
735 if(!create_next_pdu(p)) {
736 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", p->name));
740 data_returned = MIN(n, p->out_data.current_pdu_len);
742 memcpy( data, p->out_data.current_pdu, (size_t)data_returned);
743 p->out_data.current_pdu_sent += (uint32)data_returned;
747 if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
749 * We have copied all possible data into the current_pdu. This RPC is finished.
750 * Reset the talloc context to free any allocated data from this RPC.
754 DEBUG(3,("read_from_pipe: destroying talloc pool of size %u\n", talloc_pool_size(p->mem_ctx) ));
755 talloc_destroy_pool(p->mem_ctx);
757 p->mem_ctx = talloc_init();
758 if (p->mem_ctx == NULL)
759 p->fault_state = True;
764 return data_returned;
767 /****************************************************************************
768 Wait device state on a pipe. Exactly what this is for is unknown...
769 ****************************************************************************/
771 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
777 DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
780 p->priority = priority;
785 DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n",
791 /****************************************************************************
792 Set device state on a pipe. Exactly what this is for is unknown...
793 ****************************************************************************/
795 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
801 DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
802 device_state, p->name));
804 p->device_state = device_state;
809 DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n",
810 device_state, p->name));
815 /****************************************************************************
817 ****************************************************************************/
819 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
822 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
826 prs_mem_free(&p->out_data.rdata);
827 prs_mem_free(&p->in_data.data);
830 talloc_destroy(p->mem_ctx);
832 bitmap_clear(bmap, p->pnum - pipe_handle_offset);
836 DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n",
837 p->name, p->pnum, pipes_open));
839 DLIST_REMOVE(Pipes, p);
841 delete_nt_token(&p->pipe_user.nt_user_token);
842 safe_free(p->pipe_user.groups);
851 /****************************************************************************
852 Find an rpc pipe given a pipe handle in a buffer and an offset.
853 ****************************************************************************/
855 pipes_struct *get_rpc_pipe_p(char *buf, int where)
857 int pnum = SVAL(buf,where);
862 return get_rpc_pipe(pnum);
865 /****************************************************************************
866 Find an rpc pipe given a pipe handle.
867 ****************************************************************************/
869 pipes_struct *get_rpc_pipe(int pnum)
873 DEBUG(4,("search for pipe pnum=%x\n", pnum));
875 for (p=Pipes;p;p=p->next)
876 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n",
877 p->name, p->pnum, pipes_open));
879 for (p=Pipes;p;p=p->next) {
880 if (p->pnum == pnum) {