s3-rpc_client: move protos to cli_lsarpc.h
[Samba/ekacnet.git] / source3 / rpc_server / srv_pipe_hnd.c
blob847953d1862528914d9a1bb0ba7b02a36642aaae
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Largely re-written : 2005
6 * Copyright (C) Jeremy Allison 1998 - 2005
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
28 static int pipes_open;
30 static pipes_struct *InternalPipes;
32 /* TODO
33 * the following prototypes are declared here to avoid
34 * code being moved about too much for a patch to be
35 * disrupted / less obvious.
37 * these functions, and associated functions that they
38 * call, should be moved behind a .so module-loading
39 * system _anyway_. so that's the next step...
42 static int close_internal_rpc_pipe_hnd(struct pipes_struct *p);
44 /****************************************************************************
45 Internal Pipe iterator functions.
46 ****************************************************************************/
48 pipes_struct *get_first_internal_pipe(void)
50 return InternalPipes;
53 pipes_struct *get_next_internal_pipe(pipes_struct *p)
55 return p->next;
58 /****************************************************************************
59 Initialise an outgoing packet.
60 ****************************************************************************/
62 static bool pipe_init_outgoing_data(pipes_struct *p)
64 output_data *o_data = &p->out_data;
66 /* Reset the offset counters. */
67 o_data->data_sent_length = 0;
68 o_data->current_pdu_sent = 0;
70 prs_mem_free(&o_data->frag);
72 /* Free any memory in the current return data buffer. */
73 prs_mem_free(&o_data->rdata);
76 * Initialize the outgoing RPC data buffer.
77 * we will use this as the raw data area for replying to rpc requests.
78 */
79 if(!prs_init(&o_data->rdata, 128, p->mem_ctx, MARSHALL)) {
80 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
81 return False;
84 return True;
87 /****************************************************************************
88 Make an internal namedpipes structure
89 ****************************************************************************/
91 static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
92 const struct ndr_syntax_id *syntax,
93 const char *client_address,
94 struct auth_serversupplied_info *server_info)
96 pipes_struct *p;
98 DEBUG(4,("Create pipe requested %s\n",
99 get_pipe_name_from_syntax(talloc_tos(), syntax)));
101 p = TALLOC_ZERO_P(mem_ctx, struct pipes_struct);
103 if (!p) {
104 DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
105 return NULL;
108 p->mem_ctx = talloc_named(p, 0, "pipe %s %p",
109 get_pipe_name_from_syntax(talloc_tos(),
110 syntax), p);
111 if (p->mem_ctx == NULL) {
112 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
113 TALLOC_FREE(p);
114 return NULL;
117 if (!init_pipe_handle_list(p, syntax)) {
118 DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
119 TALLOC_FREE(p);
120 return NULL;
124 * Initialize the incoming RPC data buffer with one PDU worth of memory.
125 * We cheat here and say we're marshalling, as we intend to add incoming
126 * data directly into the prs_struct and we want it to auto grow. We will
127 * change the type to UNMARSALLING before processing the stream.
130 if(!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) {
131 DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
132 close_policy_by_pipe(p);
133 TALLOC_FREE(p);
134 return NULL;
137 p->server_info = copy_serverinfo(p, server_info);
138 if (p->server_info == NULL) {
139 DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n"));
140 close_policy_by_pipe(p);
141 TALLOC_FREE(p);
142 return NULL;
145 DLIST_ADD(InternalPipes, p);
147 memcpy(p->client_address, client_address, sizeof(p->client_address));
149 p->endian = RPC_LITTLE_ENDIAN;
152 * Initialize the outgoing RPC data buffer with no memory.
154 prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
156 p->syntax = *syntax;
158 DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
159 get_pipe_name_from_syntax(talloc_tos(), syntax), pipes_open));
161 talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
163 return p;
166 /****************************************************************************
167 Sets the fault state on incoming packets.
168 ****************************************************************************/
170 static void set_incoming_fault(pipes_struct *p)
172 prs_mem_free(&p->in_data.data);
173 p->in_data.pdu_needed_len = 0;
174 p->in_data.pdu_received_len = 0;
175 p->fault_state = True;
176 DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n",
177 get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
180 /****************************************************************************
181 Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
182 ****************************************************************************/
184 static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
186 size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
188 DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
189 (unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
190 (unsigned int)p->in_data.pdu_received_len ));
192 if (p->in_data.current_in_pdu == NULL) {
193 p->in_data.current_in_pdu = talloc_array(p, uint8_t,
194 RPC_HEADER_LEN);
196 if (p->in_data.current_in_pdu == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 return -1;
201 memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
202 p->in_data.pdu_received_len += len_needed_to_complete_hdr;
204 return (ssize_t)len_needed_to_complete_hdr;
207 /****************************************************************************
208 Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
209 ****************************************************************************/
211 static ssize_t unmarshall_rpc_header(pipes_struct *p)
214 * Unmarshall the header to determine the needed length.
217 prs_struct rpc_in;
219 if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
220 DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
221 set_incoming_fault(p);
222 return -1;
225 prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
226 prs_set_endian_data( &rpc_in, p->endian);
228 prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
229 p->in_data.pdu_received_len, False);
232 * Unmarshall the header as this will tell us how much
233 * data we need to read to get the complete pdu.
234 * This also sets the endian flag in rpc_in.
237 if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
238 DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
239 set_incoming_fault(p);
240 prs_mem_free(&rpc_in);
241 return -1;
245 * Validate the RPC header.
248 if(p->hdr.major != 5 && p->hdr.minor != 0) {
249 DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
250 set_incoming_fault(p);
251 prs_mem_free(&rpc_in);
252 return -1;
256 * If there's not data in the incoming buffer this should be the start of a new RPC.
259 if(prs_offset(&p->in_data.data) == 0) {
262 * AS/U doesn't set FIRST flag in a BIND packet it seems.
265 if ((p->hdr.pkt_type == DCERPC_PKT_REQUEST) && !(p->hdr.flags & DCERPC_PFC_FLAG_FIRST)) {
267 * Ensure that the FIRST flag is set. If not then we have
268 * a stream missmatch.
271 DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
272 set_incoming_fault(p);
273 prs_mem_free(&rpc_in);
274 return -1;
278 * If this is the first PDU then set the endianness
279 * flag in the pipe. We will need this when parsing all
280 * data in this RPC.
283 p->endian = rpc_in.bigendian_data;
285 DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
286 p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));
288 } else {
291 * If this is *NOT* the first PDU then check the endianness
292 * flag in the pipe is the same as that in the PDU.
295 if (p->endian != rpc_in.bigendian_data) {
296 DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
297 set_incoming_fault(p);
298 prs_mem_free(&rpc_in);
299 return -1;
304 * Ensure that the pdu length is sane.
307 if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
308 DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
309 set_incoming_fault(p);
310 prs_mem_free(&rpc_in);
311 return -1;
314 DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
315 (unsigned int)p->hdr.flags ));
317 p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
319 prs_mem_free(&rpc_in);
321 p->in_data.current_in_pdu = TALLOC_REALLOC_ARRAY(
322 p, p->in_data.current_in_pdu, uint8_t, p->hdr.frag_len);
323 if (p->in_data.current_in_pdu == NULL) {
324 DEBUG(0, ("talloc failed\n"));
325 set_incoming_fault(p);
326 return -1;
329 return 0; /* No extra data processed. */
332 /****************************************************************************
333 Call this to free any talloc'ed memory. Do this before and after processing
334 a complete PDU.
335 ****************************************************************************/
337 static void free_pipe_context(pipes_struct *p)
339 if (p->mem_ctx) {
340 DEBUG(3,("free_pipe_context: destroying talloc pool of size "
341 "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));
342 talloc_free_children(p->mem_ctx);
343 } else {
344 p->mem_ctx = talloc_named(p, 0, "pipe %s %p",
345 get_pipe_name_from_syntax(talloc_tos(),
346 &p->syntax), p);
347 if (p->mem_ctx == NULL) {
348 p->fault_state = True;
353 /****************************************************************************
354 Processes a request pdu. This will do auth processing if needed, and
355 appends the data into the complete stream if the LAST flag is not set.
356 ****************************************************************************/
358 static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
360 uint32 ss_padding_len = 0;
361 size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
362 (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
364 if(!p->pipe_bound) {
365 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
366 set_incoming_fault(p);
367 return False;
371 * Check if we need to do authentication processing.
372 * This is only done on requests, not binds.
376 * Read the RPC request header.
379 if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
380 DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
381 set_incoming_fault(p);
382 return False;
385 switch(p->auth.auth_type) {
386 case PIPE_AUTH_TYPE_NONE:
387 break;
389 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
390 case PIPE_AUTH_TYPE_NTLMSSP:
392 NTSTATUS status;
393 if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
394 DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
395 DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
396 set_incoming_fault(p);
397 return False;
399 break;
402 case PIPE_AUTH_TYPE_SCHANNEL:
403 if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
404 DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
405 set_incoming_fault(p);
406 return False;
408 break;
410 default:
411 DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
412 set_incoming_fault(p);
413 return False;
416 /* Now we've done the sign/seal we can remove any padding data. */
417 if (data_len > ss_padding_len) {
418 data_len -= ss_padding_len;
422 * Check the data length doesn't go over the 15Mb limit.
423 * increased after observing a bug in the Windows NT 4.0 SP6a
424 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
425 * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002
428 if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) {
429 DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
430 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
431 set_incoming_fault(p);
432 return False;
436 * Append the data portion into the buffer and return.
439 if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
440 DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
441 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
442 set_incoming_fault(p);
443 return False;
446 if(p->hdr.flags & DCERPC_PFC_FLAG_LAST) {
447 bool ret = False;
449 * Ok - we finally have a complete RPC stream.
450 * Call the rpc command to process it.
454 * Ensure the internal prs buffer size is *exactly* the same
455 * size as the current offset.
458 if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
459 DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
460 set_incoming_fault(p);
461 return False;
465 * Set the parse offset to the start of the data and set the
466 * prs_struct to UNMARSHALL.
469 prs_set_offset(&p->in_data.data, 0);
470 prs_switch_type(&p->in_data.data, UNMARSHALL);
473 * Process the complete data stream here.
476 free_pipe_context(p);
478 if(pipe_init_outgoing_data(p)) {
479 ret = api_pipe_request(p);
482 free_pipe_context(p);
485 * We have consumed the whole data stream. Set back to
486 * marshalling and set the offset back to the start of
487 * the buffer to re-use it (we could also do a prs_mem_free()
488 * and then re_init on the next start of PDU. Not sure which
489 * is best here.... JRA.
492 prs_switch_type(&p->in_data.data, MARSHALL);
493 prs_set_offset(&p->in_data.data, 0);
494 return ret;
497 return True;
500 /****************************************************************************
501 Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
502 already been parsed and stored in p->hdr.
503 ****************************************************************************/
505 static void process_complete_pdu(pipes_struct *p)
507 prs_struct rpc_in;
508 size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;
509 char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];
510 bool reply = False;
512 if(p->fault_state) {
513 DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
514 get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
515 set_incoming_fault(p);
516 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
517 return;
520 prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
523 * Ensure we're using the corrent endianness for both the
524 * RPC header flags and the raw data we will be reading from.
527 prs_set_endian_data( &rpc_in, p->endian);
528 prs_set_endian_data( &p->in_data.data, p->endian);
530 prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
532 DEBUG(10,("process_complete_pdu: processing packet type %u\n",
533 (unsigned int)p->hdr.pkt_type ));
535 switch (p->hdr.pkt_type) {
536 case DCERPC_PKT_REQUEST:
537 reply = process_request_pdu(p, &rpc_in);
538 break;
540 case DCERPC_PKT_PING: /* CL request - ignore... */
541 DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
542 (unsigned int)p->hdr.pkt_type,
543 get_pipe_name_from_syntax(talloc_tos(),
544 &p->syntax)));
545 break;
547 case DCERPC_PKT_RESPONSE: /* No responses here. */
548 DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_RESPONSE received from client on pipe %s.\n",
549 get_pipe_name_from_syntax(talloc_tos(),
550 &p->syntax)));
551 break;
553 case DCERPC_PKT_FAULT:
554 case DCERPC_PKT_WORKING: /* CL request - reply to a ping when a call in process. */
555 case DCERPC_PKT_NOCALL: /* CL - server reply to a ping call. */
556 case DCERPC_PKT_REJECT:
557 case DCERPC_PKT_ACK:
558 case DCERPC_PKT_CL_CANCEL:
559 case DCERPC_PKT_FACK:
560 case DCERPC_PKT_CANCEL_ACK:
561 DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
562 (unsigned int)p->hdr.pkt_type,
563 get_pipe_name_from_syntax(talloc_tos(),
564 &p->syntax)));
565 break;
567 case DCERPC_PKT_BIND:
569 * We assume that a pipe bind is only in one pdu.
571 if(pipe_init_outgoing_data(p)) {
572 reply = api_pipe_bind_req(p, &rpc_in);
574 break;
576 case DCERPC_PKT_BIND_ACK:
577 case DCERPC_PKT_BIND_NAK:
578 DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK packet type %u received on pipe %s.\n",
579 (unsigned int)p->hdr.pkt_type,
580 get_pipe_name_from_syntax(talloc_tos(),
581 &p->syntax)));
582 break;
585 case DCERPC_PKT_ALTER:
587 * We assume that a pipe bind is only in one pdu.
589 if(pipe_init_outgoing_data(p)) {
590 reply = api_pipe_alter_context(p, &rpc_in);
592 break;
594 case DCERPC_PKT_ALTER_RESP:
595 DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_ALTER_RESP on pipe %s: Should only be server -> client.\n",
596 get_pipe_name_from_syntax(talloc_tos(),
597 &p->syntax)));
598 break;
600 case DCERPC_PKT_AUTH3:
602 * The third packet in an NTLMSSP auth exchange.
604 if(pipe_init_outgoing_data(p)) {
605 reply = api_pipe_bind_auth3(p, &rpc_in);
607 break;
609 case DCERPC_PKT_SHUTDOWN:
610 DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_SHUTDOWN on pipe %s: Should only be server -> client.\n",
611 get_pipe_name_from_syntax(talloc_tos(),
612 &p->syntax)));
613 break;
615 case DCERPC_PKT_CO_CANCEL:
616 /* For now just free all client data and continue processing. */
617 DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL. Abandoning rpc call.\n"));
618 /* As we never do asynchronous RPC serving, we can never cancel a
619 call (as far as I know). If we ever did we'd have to send a cancel_ack
620 reply. For now, just free all client data and continue processing. */
621 reply = True;
622 break;
623 #if 0
624 /* Enable this if we're doing async rpc. */
625 /* We must check the call-id matches the outstanding callid. */
626 if(pipe_init_outgoing_data(p)) {
627 /* Send a cancel_ack PDU reply. */
628 /* We should probably check the auth-verifier here. */
629 reply = setup_cancel_ack_reply(p, &rpc_in);
631 break;
632 #endif
634 case DCERPC_PKT_ORPHANED:
635 /* We should probably check the auth-verifier here.
636 For now just free all client data and continue processing. */
637 DEBUG(3,("process_complete_pdu: DCERPC_PKT_ORPHANED. Abandoning rpc call.\n"));
638 reply = True;
639 break;
641 default:
642 DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
643 break;
646 /* Reset to little endian. Probably don't need this but it won't hurt. */
647 prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN);
649 if (!reply) {
650 DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on "
651 "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(),
652 &p->syntax)));
653 set_incoming_fault(p);
654 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
655 prs_mem_free(&rpc_in);
656 } else {
658 * Reset the lengths. We're ready for a new pdu.
660 TALLOC_FREE(p->in_data.current_in_pdu);
661 p->in_data.pdu_needed_len = 0;
662 p->in_data.pdu_received_len = 0;
665 prs_mem_free(&rpc_in);
668 /****************************************************************************
669 Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
670 ****************************************************************************/
672 static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
674 size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
676 DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
677 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
678 (unsigned int)n ));
680 if(data_to_copy == 0) {
682 * This is an error - data is being received and there is no
683 * space in the PDU. Free the received data and go into the fault state.
685 DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
686 incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
687 set_incoming_fault(p);
688 return -1;
692 * If we have no data already, wait until we get at least a RPC_HEADER_LEN
693 * number of bytes before we can do anything.
696 if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
698 * Always return here. If we have more data then the RPC_HEADER
699 * will be processed the next time around the loop.
701 return fill_rpc_header(p, data, data_to_copy);
705 * At this point we know we have at least an RPC_HEADER_LEN amount of data
706 * stored in current_in_pdu.
710 * If pdu_needed_len is zero this is a new pdu.
711 * Unmarshall the header so we know how much more
712 * data we need, then loop again.
715 if(p->in_data.pdu_needed_len == 0) {
716 ssize_t rret = unmarshall_rpc_header(p);
717 if (rret == -1 || p->in_data.pdu_needed_len > 0) {
718 return rret;
720 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists
721 of an RPC_HEADER only. This is a DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or DCERPC_PKT_ORPHANED
722 pdu type. Deal with this in process_complete_pdu(). */
726 * Ok - at this point we have a valid RPC_HEADER in p->hdr.
727 * Keep reading until we have a full pdu.
730 data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
733 * Copy as much of the data as we need into the current_in_pdu buffer.
734 * pdu_needed_len becomes zero when we have a complete pdu.
737 memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
738 p->in_data.pdu_received_len += data_to_copy;
739 p->in_data.pdu_needed_len -= data_to_copy;
742 * Do we have a complete PDU ?
743 * (return the number of bytes handled in the call)
746 if(p->in_data.pdu_needed_len == 0) {
747 process_complete_pdu(p);
748 return data_to_copy;
751 DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
752 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
754 return (ssize_t)data_to_copy;
757 /****************************************************************************
758 Accepts incoming data on an internal rpc pipe.
759 ****************************************************************************/
761 static ssize_t write_to_internal_pipe(struct pipes_struct *p, char *data, size_t n)
763 size_t data_left = n;
765 while(data_left) {
766 ssize_t data_used;
768 DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
770 data_used = process_incoming_data(p, data, data_left);
772 DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
774 if(data_used < 0) {
775 return -1;
778 data_left -= data_used;
779 data += data_used;
782 return n;
785 /****************************************************************************
786 Replies to a request to read data from a pipe.
788 Headers are interspersed with the data at PDU intervals. By the time
789 this function is called, the start of the data could possibly have been
790 read by an SMBtrans (file_offset != 0).
792 Calling create_rpc_reply() here is a hack. The data should already
793 have been prepared into arrays of headers + data stream sections.
794 ****************************************************************************/
796 static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_t n,
797 bool *is_data_outstanding)
799 uint32 pdu_remaining = 0;
800 ssize_t data_returned = 0;
802 if (!p) {
803 DEBUG(0,("read_from_pipe: pipe not open\n"));
804 return -1;
807 DEBUG(6,(" name: %s len: %u\n",
808 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
809 (unsigned int)n));
812 * We cannot return more than one PDU length per
813 * read request.
817 * This condition should result in the connection being closed.
818 * Netapp filers seem to set it to 0xffff which results in domain
819 * authentications failing. Just ignore it so things work.
822 if(n > RPC_MAX_PDU_FRAG_LEN) {
823 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
824 "pipe %s. We can only service %d sized reads.\n",
825 (unsigned int)n,
826 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
827 RPC_MAX_PDU_FRAG_LEN ));
828 n = RPC_MAX_PDU_FRAG_LEN;
832 * Determine if there is still data to send in the
833 * pipe PDU buffer. Always send this first. Never
834 * send more than is left in the current PDU. The
835 * client should send a new read request for a new
836 * PDU.
839 pdu_remaining = prs_offset(&p->out_data.frag)
840 - p->out_data.current_pdu_sent;
842 if (pdu_remaining > 0) {
843 data_returned = (ssize_t)MIN(n, pdu_remaining);
845 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
846 "current_pdu_sent = %u returning %d bytes.\n",
847 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
848 (unsigned int)prs_offset(&p->out_data.frag),
849 (unsigned int)p->out_data.current_pdu_sent,
850 (int)data_returned));
852 memcpy(data,
853 prs_data_p(&p->out_data.frag)
854 + p->out_data.current_pdu_sent,
855 data_returned);
857 p->out_data.current_pdu_sent += (uint32)data_returned;
858 goto out;
862 * At this point p->current_pdu_len == p->current_pdu_sent (which
863 * may of course be zero if this is the first return fragment.
866 DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
867 "= %u, prs_offset(&p->out_data.rdata) = %u.\n",
868 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
869 (int)p->fault_state,
870 (unsigned int)p->out_data.data_sent_length,
871 (unsigned int)prs_offset(&p->out_data.rdata) ));
873 if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
875 * We have sent all possible data, return 0.
877 data_returned = 0;
878 goto out;
882 * We need to create a new PDU from the data left in p->rdata.
883 * Create the header/data/footers. This also sets up the fields
884 * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
885 * and stores the outgoing PDU in p->current_pdu.
888 if(!create_next_pdu(p)) {
889 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
890 get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
891 return -1;
894 data_returned = MIN(n, prs_offset(&p->out_data.frag));
896 memcpy( data, prs_data_p(&p->out_data.frag), (size_t)data_returned);
897 p->out_data.current_pdu_sent += (uint32)data_returned;
899 out:
900 (*is_data_outstanding) = prs_offset(&p->out_data.frag) > n;
902 if (p->out_data.current_pdu_sent == prs_offset(&p->out_data.frag)) {
903 /* We've returned everything in the out_data.frag
904 * so we're done with this pdu. Free it and reset
905 * current_pdu_sent. */
906 p->out_data.current_pdu_sent = 0;
907 prs_mem_free(&p->out_data.frag);
909 return data_returned;
912 /****************************************************************************
913 Close an rpc pipe.
914 ****************************************************************************/
916 static int close_internal_rpc_pipe_hnd(struct pipes_struct *p)
918 if (!p) {
919 DEBUG(0,("Invalid pipe in close_internal_rpc_pipe_hnd\n"));
920 return False;
923 prs_mem_free(&p->out_data.frag);
924 prs_mem_free(&p->out_data.rdata);
925 prs_mem_free(&p->in_data.data);
927 if (p->auth.auth_data_free_func) {
928 (*p->auth.auth_data_free_func)(&p->auth);
931 free_pipe_rpc_context( p->contexts );
933 /* Free the handles database. */
934 close_policy_by_pipe(p);
936 DLIST_REMOVE(InternalPipes, p);
938 ZERO_STRUCTP(p);
940 return 0;
943 bool fsp_is_np(struct files_struct *fsp)
945 enum FAKE_FILE_TYPE type;
947 if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
948 return false;
951 type = fsp->fake_file_handle->type;
953 return ((type == FAKE_FILE_TYPE_NAMED_PIPE)
954 || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY));
957 struct np_proxy_state {
958 struct tevent_queue *read_queue;
959 struct tevent_queue *write_queue;
960 int fd;
962 uint8_t *msg;
963 size_t sent;
966 static int np_proxy_state_destructor(struct np_proxy_state *state)
968 if (state->fd != -1) {
969 close(state->fd);
971 return 0;
974 static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
975 const char *pipe_name,
976 struct auth_serversupplied_info *server_info)
978 struct np_proxy_state *result;
979 struct sockaddr_un addr;
980 char *socket_path;
981 const char *socket_dir;
983 DATA_BLOB req_blob;
984 struct netr_SamInfo3 *info3;
985 struct named_pipe_auth_req req;
986 DATA_BLOB rep_blob;
987 uint8 rep_buf[20];
988 struct named_pipe_auth_rep rep;
989 enum ndr_err_code ndr_err;
990 NTSTATUS status;
991 ssize_t written;
993 result = talloc(mem_ctx, struct np_proxy_state);
994 if (result == NULL) {
995 DEBUG(0, ("talloc failed\n"));
996 return NULL;
999 result->fd = socket(AF_UNIX, SOCK_STREAM, 0);
1000 if (result->fd == -1) {
1001 DEBUG(10, ("socket(2) failed: %s\n", strerror(errno)));
1002 goto fail;
1004 talloc_set_destructor(result, np_proxy_state_destructor);
1006 ZERO_STRUCT(addr);
1007 addr.sun_family = AF_UNIX;
1009 socket_dir = lp_parm_const_string(
1010 GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
1011 get_dyn_NCALRPCDIR());
1012 if (socket_dir == NULL) {
1013 DEBUG(0, ("externan_rpc_pipe:socket_dir not set\n"));
1014 goto fail;
1017 socket_path = talloc_asprintf(talloc_tos(), "%s/np/%s",
1018 socket_dir, pipe_name);
1019 if (socket_path == NULL) {
1020 DEBUG(0, ("talloc_asprintf failed\n"));
1021 goto fail;
1023 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
1024 TALLOC_FREE(socket_path);
1026 become_root();
1027 if (sys_connect(result->fd, (struct sockaddr *)&addr) == -1) {
1028 unbecome_root();
1029 DEBUG(0, ("connect(%s) failed: %s\n", addr.sun_path,
1030 strerror(errno)));
1031 goto fail;
1033 unbecome_root();
1035 info3 = talloc(talloc_tos(), struct netr_SamInfo3);
1036 if (info3 == NULL) {
1037 DEBUG(0, ("talloc failed\n"));
1038 goto fail;
1041 status = serverinfo_to_SamInfo3(server_info, NULL, 0, info3);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 TALLOC_FREE(info3);
1044 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
1045 nt_errstr(status)));
1046 goto fail;
1049 req.level = 1;
1050 req.info.info1 = *info3;
1052 ndr_err = ndr_push_struct_blob(&req_blob, talloc_tos(), &req,
1053 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
1055 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1056 DEBUG(10, ("ndr_push_named_pipe_auth_req failed: %s\n",
1057 ndr_errstr(ndr_err)));
1058 goto fail;
1061 DEBUG(10, ("named_pipe_auth_req(client)[%u]\n", (uint32_t)req_blob.length));
1062 dump_data(10, req_blob.data, req_blob.length);
1064 written = write_data(result->fd, (char *)req_blob.data,
1065 req_blob.length);
1066 if (written == -1) {
1067 DEBUG(3, ("Could not write auth req data to RPC server\n"));
1068 goto fail;
1071 status = read_data(result->fd, (char *)rep_buf, sizeof(rep_buf));
1072 if (!NT_STATUS_IS_OK(status)) {
1073 DEBUG(3, ("Could not read auth result\n"));
1074 goto fail;
1077 rep_blob = data_blob_const(rep_buf, sizeof(rep_buf));
1079 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n", (uint32_t)rep_blob.length));
1080 dump_data(10, rep_blob.data, rep_blob.length);
1082 ndr_err = ndr_pull_struct_blob(&rep_blob, talloc_tos(), &rep,
1083 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
1085 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1086 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
1087 ndr_errstr(ndr_err)));
1088 goto fail;
1091 if (rep.length != 16) {
1092 DEBUG(0, ("req invalid length: %u != 16\n",
1093 rep.length));
1094 goto fail;
1097 if (strcmp(NAMED_PIPE_AUTH_MAGIC, rep.magic) != 0) {
1098 DEBUG(0, ("req invalid magic: %s != %s\n",
1099 rep.magic, NAMED_PIPE_AUTH_MAGIC));
1100 goto fail;
1103 if (!NT_STATUS_IS_OK(rep.status)) {
1104 DEBUG(0, ("req failed: %s\n",
1105 nt_errstr(rep.status)));
1106 goto fail;
1109 if (rep.level != 1) {
1110 DEBUG(0, ("req invalid level: %u != 1\n",
1111 rep.level));
1112 goto fail;
1115 result->msg = NULL;
1117 result->read_queue = tevent_queue_create(result, "np_read");
1118 if (result->read_queue == NULL) {
1119 goto fail;
1121 result->write_queue = tevent_queue_create(result, "np_write");
1122 if (result->write_queue == NULL) {
1123 goto fail;
1126 return result;
1128 fail:
1129 TALLOC_FREE(result);
1130 return NULL;
1133 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
1134 const char *client_address,
1135 struct auth_serversupplied_info *server_info,
1136 struct fake_file_handle **phandle)
1138 const char **proxy_list;
1139 struct fake_file_handle *handle;
1141 proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
1143 handle = talloc(mem_ctx, struct fake_file_handle);
1144 if (handle == NULL) {
1145 return NT_STATUS_NO_MEMORY;
1148 if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
1149 struct np_proxy_state *p;
1151 p = make_external_rpc_pipe_p(handle, name, server_info);
1153 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
1154 handle->private_data = p;
1155 } else {
1156 struct pipes_struct *p;
1157 struct ndr_syntax_id syntax;
1159 if (!is_known_pipename(name, &syntax)) {
1160 TALLOC_FREE(handle);
1161 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1164 p = make_internal_rpc_pipe_p(handle, &syntax, client_address,
1165 server_info);
1167 handle->type = FAKE_FILE_TYPE_NAMED_PIPE;
1168 handle->private_data = p;
1171 if (handle->private_data == NULL) {
1172 TALLOC_FREE(handle);
1173 return NT_STATUS_PIPE_NOT_AVAILABLE;
1176 *phandle = handle;
1178 return NT_STATUS_OK;
1181 struct np_write_state {
1182 struct event_context *ev;
1183 struct np_proxy_state *p;
1184 struct iovec iov;
1185 ssize_t nwritten;
1188 static void np_write_done(struct tevent_req *subreq);
1190 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
1191 struct fake_file_handle *handle,
1192 const uint8_t *data, size_t len)
1194 struct tevent_req *req;
1195 struct np_write_state *state;
1196 NTSTATUS status;
1198 DEBUG(6, ("np_write_send: len: %d\n", (int)len));
1199 dump_data(50, data, len);
1201 req = tevent_req_create(mem_ctx, &state, struct np_write_state);
1202 if (req == NULL) {
1203 return NULL;
1206 if (len == 0) {
1207 state->nwritten = 0;
1208 status = NT_STATUS_OK;
1209 goto post_status;
1212 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
1213 struct pipes_struct *p = talloc_get_type_abort(
1214 handle->private_data, struct pipes_struct);
1216 state->nwritten = write_to_internal_pipe(p, (char *)data, len);
1218 status = (state->nwritten >= 0)
1219 ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
1220 goto post_status;
1223 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
1224 struct np_proxy_state *p = talloc_get_type_abort(
1225 handle->private_data, struct np_proxy_state);
1226 struct tevent_req *subreq;
1228 state->ev = ev;
1229 state->p = p;
1230 state->iov.iov_base = CONST_DISCARD(void *, data);
1231 state->iov.iov_len = len;
1233 subreq = writev_send(state, ev, p->write_queue, p->fd,
1234 false, &state->iov, 1);
1235 if (subreq == NULL) {
1236 goto fail;
1238 tevent_req_set_callback(subreq, np_write_done, req);
1239 return req;
1242 status = NT_STATUS_INVALID_HANDLE;
1243 post_status:
1244 if (NT_STATUS_IS_OK(status)) {
1245 tevent_req_done(req);
1246 } else {
1247 tevent_req_nterror(req, status);
1249 return tevent_req_post(req, ev);
1250 fail:
1251 TALLOC_FREE(req);
1252 return NULL;
1255 static void np_write_done(struct tevent_req *subreq)
1257 struct tevent_req *req = tevent_req_callback_data(
1258 subreq, struct tevent_req);
1259 struct np_write_state *state = tevent_req_data(
1260 req, struct np_write_state);
1261 ssize_t received;
1262 int err;
1264 received = writev_recv(subreq, &err);
1265 if (received < 0) {
1266 tevent_req_nterror(req, map_nt_error_from_unix(err));
1267 return;
1269 state->nwritten = received;
1270 tevent_req_done(req);
1273 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
1275 struct np_write_state *state = tevent_req_data(
1276 req, struct np_write_state);
1277 NTSTATUS status;
1279 if (tevent_req_is_nterror(req, &status)) {
1280 return status;
1282 *pnwritten = state->nwritten;
1283 return NT_STATUS_OK;
1286 static ssize_t rpc_frag_more_fn(uint8_t *buf, size_t buflen, void *priv)
1288 prs_struct hdr_prs;
1289 struct rpc_hdr_info hdr;
1290 bool ret;
1292 if (buflen > RPC_HEADER_LEN) {
1293 return 0;
1295 prs_init_empty(&hdr_prs, talloc_tos(), UNMARSHALL);
1296 prs_give_memory(&hdr_prs, (char *)buf, RPC_HEADER_LEN, false);
1297 ret = smb_io_rpc_hdr("", &hdr, &hdr_prs, 0);
1298 prs_mem_free(&hdr_prs);
1300 if (!ret) {
1301 return -1;
1304 return (hdr.frag_len - RPC_HEADER_LEN);
1307 struct np_read_state {
1308 struct event_context *ev;
1309 struct np_proxy_state *p;
1310 uint8_t *data;
1311 size_t len;
1313 size_t nread;
1314 bool is_data_outstanding;
1317 static void np_read_trigger(struct tevent_req *req, void *private_data);
1318 static void np_read_done(struct tevent_req *subreq);
1320 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
1321 struct fake_file_handle *handle,
1322 uint8_t *data, size_t len)
1324 struct tevent_req *req;
1325 struct np_read_state *state;
1326 NTSTATUS status;
1328 req = tevent_req_create(mem_ctx, &state, struct np_read_state);
1329 if (req == NULL) {
1330 return NULL;
1333 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
1334 struct pipes_struct *p = talloc_get_type_abort(
1335 handle->private_data, struct pipes_struct);
1337 state->nread = read_from_internal_pipe(
1338 p, (char *)data, len, &state->is_data_outstanding);
1340 status = (state->nread >= 0)
1341 ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
1342 goto post_status;
1345 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
1346 struct np_proxy_state *p = talloc_get_type_abort(
1347 handle->private_data, struct np_proxy_state);
1349 if (p->msg != NULL) {
1350 size_t thistime;
1352 thistime = MIN(talloc_get_size(p->msg) - p->sent,
1353 len);
1355 memcpy(data, p->msg+p->sent, thistime);
1356 state->nread = thistime;
1357 p->sent += thistime;
1359 if (p->sent < talloc_get_size(p->msg)) {
1360 state->is_data_outstanding = true;
1361 } else {
1362 state->is_data_outstanding = false;
1363 TALLOC_FREE(p->msg);
1365 status = NT_STATUS_OK;
1366 goto post_status;
1369 state->ev = ev;
1370 state->p = p;
1371 state->data = data;
1372 state->len = len;
1374 if (!tevent_queue_add(p->read_queue, ev, req, np_read_trigger,
1375 NULL)) {
1376 goto fail;
1378 return req;
1381 status = NT_STATUS_INVALID_HANDLE;
1382 post_status:
1383 if (NT_STATUS_IS_OK(status)) {
1384 tevent_req_done(req);
1385 } else {
1386 tevent_req_nterror(req, status);
1388 return tevent_req_post(req, ev);
1389 fail:
1390 TALLOC_FREE(req);
1391 return NULL;
1394 static void np_read_trigger(struct tevent_req *req, void *private_data)
1396 struct np_read_state *state = tevent_req_data(
1397 req, struct np_read_state);
1398 struct tevent_req *subreq;
1400 subreq = read_packet_send(state, state->ev, state->p->fd,
1401 RPC_HEADER_LEN, rpc_frag_more_fn, NULL);
1402 if (tevent_req_nomem(subreq, req)) {
1403 return;
1405 tevent_req_set_callback(subreq, np_read_done, req);
1408 static void np_read_done(struct tevent_req *subreq)
1410 struct tevent_req *req = tevent_req_callback_data(
1411 subreq, struct tevent_req);
1412 struct np_read_state *state = tevent_req_data(
1413 req, struct np_read_state);
1414 ssize_t received;
1415 size_t thistime;
1416 int err;
1418 received = read_packet_recv(subreq, state->p, &state->p->msg, &err);
1419 TALLOC_FREE(subreq);
1420 if (received == -1) {
1421 tevent_req_nterror(req, map_nt_error_from_unix(err));
1422 return;
1425 thistime = MIN(received, state->len);
1427 memcpy(state->data, state->p->msg, thistime);
1428 state->p->sent = thistime;
1429 state->nread = thistime;
1431 if (state->p->sent < received) {
1432 state->is_data_outstanding = true;
1433 } else {
1434 TALLOC_FREE(state->p->msg);
1435 state->is_data_outstanding = false;
1438 tevent_req_done(req);
1439 return;
1442 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
1443 bool *is_data_outstanding)
1445 struct np_read_state *state = tevent_req_data(
1446 req, struct np_read_state);
1447 NTSTATUS status;
1449 if (tevent_req_is_nterror(req, &status)) {
1450 return status;
1452 *nread = state->nread;
1453 *is_data_outstanding = state->is_data_outstanding;
1454 return NT_STATUS_OK;
1458 * @brief Create a new RPC client context which uses a local dispatch function.
1460 * @param[in] mem_ctx The memory context to use.
1462 * @param[in] abstract_syntax Normally the syntax_id of the autogenerated
1463 * ndr_table_<name>.
1465 * @param[in] dispatch The corresponding autogenerated dispatch function
1466 * rpc_<name>_dispatch.
1468 * @param[in] serversupplied_info The server supplied authentication function.
1470 * @param[out] presult A pointer to store the connected rpc client pipe.
1472 * @return NT_STATUS_OK on success, a corresponding NT status if an
1473 * error occured.
1475 * @code
1476 * struct rpc_pipe_client *winreg_pipe;
1477 * NTSTATUS status;
1479 * status = rpc_pipe_open_internal(tmp_ctx,
1480 * &ndr_table_winreg.syntax_id,
1481 * rpc_winreg_dispatch,
1482 * p->server_info,
1483 * &winreg_pipe);
1484 * @endcode
1486 NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
1487 const struct ndr_syntax_id *abstract_syntax,
1488 NTSTATUS (*dispatch) (struct rpc_pipe_client *cli,
1489 TALLOC_CTX *mem_ctx,
1490 const struct ndr_interface_table *table,
1491 uint32_t opnum, void *r),
1492 struct auth_serversupplied_info *serversupplied_info,
1493 struct rpc_pipe_client **presult)
1495 struct rpc_pipe_client *result;
1497 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
1498 if (result == NULL) {
1499 return NT_STATUS_NO_MEMORY;
1502 result->abstract_syntax = *abstract_syntax;
1503 result->transfer_syntax = ndr_transfer_syntax;
1504 result->dispatch = dispatch;
1506 result->pipes_struct = make_internal_rpc_pipe_p(
1507 result, abstract_syntax, "", serversupplied_info);
1508 if (result->pipes_struct == NULL) {
1509 TALLOC_FREE(result);
1510 return NT_STATUS_NO_MEMORY;
1513 result->max_xmit_frag = -1;
1514 result->max_recv_frag = -1;
1516 *presult = result;
1517 return NT_STATUS_OK;