rpc_server/srv_pipe_hnd.c

説明を見る。
00001 /* 
00002  *  Unix SMB/CIFS implementation.
00003  *  RPC Pipe client / server routines
00004  *  Copyright (C) Andrew Tridgell              1992-1998,
00005  *  Largely re-written : 2005
00006  *  Copyright (C) Jeremy Allison                1998 - 2005
00007  *  
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *  
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *  
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021  */
00022 
00023 #include "includes.h"
00024 
00025 #undef DBGC_CLASS
00026 #define DBGC_CLASS DBGC_RPC_SRV
00027 
00028 #define PIPE            "\\PIPE\\"
00029 #define PIPELEN         strlen(PIPE)
00030 
00031 static smb_np_struct *chain_p;
00032 static int pipes_open;
00033 
00034 /*
00035  * Sometimes I can't decide if I hate Windows printer driver
00036  * writers more than I hate the Windows spooler service driver
00037  * writers. This gets around a combination of bugs in the spooler
00038  * and the HP 8500 PCL driver that causes a spooler spin. JRA.
00039  *
00040  * bumped up from 20 -> 64 after viewing traffic from WordPerfect
00041  * 2002 running on NT 4.- SP6
00042  * bumped up from 64 -> 256 after viewing traffic from con2prt
00043  * for lots of printers on a WinNT 4.x SP6 box.
00044  */
00045  
00046 #ifndef MAX_OPEN_SPOOLSS_PIPES
00047 #define MAX_OPEN_SPOOLSS_PIPES 256
00048 #endif
00049 static int current_spoolss_pipes_open;
00050 
00051 static smb_np_struct *Pipes;
00052 static pipes_struct *InternalPipes;
00053 static struct bitmap *bmap;
00054 
00055 /* TODO
00056  * the following prototypes are declared here to avoid
00057  * code being moved about too much for a patch to be
00058  * disrupted / less obvious.
00059  *
00060  * these functions, and associated functions that they
00061  * call, should be moved behind a .so module-loading
00062  * system _anyway_.  so that's the next step...
00063  */
00064 
00065 static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,
00066                 BOOL *is_data_outstanding);
00067 static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n);
00068 static BOOL close_internal_rpc_pipe_hnd(void *np_conn);
00069 static void *make_internal_rpc_pipe_p(char *pipe_name, 
00070                               connection_struct *conn, uint16 vuid);
00071 
00072 /****************************************************************************
00073  Pipe iterator functions.
00074 ****************************************************************************/
00075 
00076 smb_np_struct *get_first_pipe(void)
00077 {
00078         return Pipes;
00079 }
00080 
00081 smb_np_struct *get_next_pipe(smb_np_struct *p)
00082 {
00083         return p->next;
00084 }
00085 
00086 /****************************************************************************
00087  Internal Pipe iterator functions.
00088 ****************************************************************************/
00089 
00090 pipes_struct *get_first_internal_pipe(void)
00091 {
00092         return InternalPipes;
00093 }
00094 
00095 pipes_struct *get_next_internal_pipe(pipes_struct *p)
00096 {
00097         return p->next;
00098 }
00099 
00100 /* this must be larger than the sum of the open files and directories */
00101 static int pipe_handle_offset;
00102 
00103 /****************************************************************************
00104  Set the pipe_handle_offset. Called from smbd/files.c
00105 ****************************************************************************/
00106 
00107 void set_pipe_handle_offset(int max_open_files)
00108 {
00109         if(max_open_files < 0x7000) {
00110                 pipe_handle_offset = 0x7000;
00111         } else {
00112                 pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
00113         }
00114 }
00115 
00116 /****************************************************************************
00117  Reset pipe chain handle number.
00118 ****************************************************************************/
00119 
00120 void reset_chain_p(void)
00121 {
00122         chain_p = NULL;
00123 }
00124 
00125 /****************************************************************************
00126  Initialise pipe handle states.
00127 ****************************************************************************/
00128 
00129 void init_rpc_pipe_hnd(void)
00130 {
00131         bmap = bitmap_allocate(MAX_OPEN_PIPES);
00132         if (!bmap) {
00133                 exit_server("out of memory in init_rpc_pipe_hnd");
00134         }
00135 }
00136 
00137 /****************************************************************************
00138  Initialise an outgoing packet.
00139 ****************************************************************************/
00140 
00141 static BOOL pipe_init_outgoing_data(pipes_struct *p)
00142 {
00143         output_data *o_data = &p->out_data;
00144 
00145         /* Reset the offset counters. */
00146         o_data->data_sent_length = 0;
00147         o_data->current_pdu_len = 0;
00148         o_data->current_pdu_sent = 0;
00149 
00150         memset(o_data->current_pdu, '\0', sizeof(o_data->current_pdu));
00151 
00152         /* Free any memory in the current return data buffer. */
00153         prs_mem_free(&o_data->rdata);
00154 
00155         /*
00156          * Initialize the outgoing RPC data buffer.
00157          * we will use this as the raw data area for replying to rpc requests.
00158          */     
00159         if(!prs_init(&o_data->rdata, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
00160                 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
00161                 return False;
00162         }
00163 
00164         return True;
00165 }
00166 
00167 /****************************************************************************
00168  Find first available pipe slot.
00169 ****************************************************************************/
00170 
00171 smb_np_struct *open_rpc_pipe_p(char *pipe_name, 
00172                               connection_struct *conn, uint16 vuid)
00173 {
00174         int i;
00175         smb_np_struct *p, *p_it;
00176         static int next_pipe;
00177         BOOL is_spoolss_pipe = False;
00178 
00179         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
00180                  pipe_name, pipes_open));
00181 
00182         if (strstr(pipe_name, "spoolss")) {
00183                 is_spoolss_pipe = True;
00184         }
00185  
00186         if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) {
00187                 DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n",
00188                         pipe_name ));
00189                 return NULL;
00190         }
00191 
00192         /* not repeating pipe numbers makes it easier to track things in 
00193            log files and prevents client bugs where pipe numbers are reused
00194            over connection restarts */
00195 
00196         if (next_pipe == 0) {
00197                 next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
00198         }
00199 
00200         i = bitmap_find(bmap, next_pipe);
00201 
00202         if (i == -1) {
00203                 DEBUG(0,("ERROR! Out of pipe structures\n"));
00204                 return NULL;
00205         }
00206 
00207         next_pipe = (i+1) % MAX_OPEN_PIPES;
00208 
00209         for (p = Pipes; p; p = p->next) {
00210                 DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum));  
00211         }
00212 
00213         p = SMB_MALLOC_P(smb_np_struct);
00214         if (!p) {
00215                 DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
00216                 return NULL;
00217         }
00218 
00219         ZERO_STRUCTP(p);
00220 
00221         /* add a dso mechanism instead of this, here */
00222 
00223         p->namedpipe_create = make_internal_rpc_pipe_p;
00224         p->namedpipe_read = read_from_internal_pipe;
00225         p->namedpipe_write = write_to_internal_pipe;
00226         p->namedpipe_close = close_internal_rpc_pipe_hnd;
00227 
00228         p->np_state = p->namedpipe_create(pipe_name, conn, vuid);
00229 
00230         if (p->np_state == NULL) {
00231                 DEBUG(0,("open_rpc_pipe_p: make_internal_rpc_pipe_p failed.\n"));
00232                 SAFE_FREE(p);
00233                 return NULL;
00234         }
00235 
00236         DLIST_ADD(Pipes, p);
00237 
00238         /*
00239          * Initialize the incoming RPC data buffer with one PDU worth of memory.
00240          * We cheat here and say we're marshalling, as we intend to add incoming
00241          * data directly into the prs_struct and we want it to auto grow. We will
00242          * change the type to UNMARSALLING before processing the stream.
00243          */
00244 
00245         bitmap_set(bmap, i);
00246         i += pipe_handle_offset;
00247 
00248         pipes_open++;
00249 
00250         p->pnum = i;
00251 
00252         p->open = True;
00253         p->device_state = 0;
00254         p->priority = 0;
00255         p->conn = conn;
00256         p->vuid  = vuid;
00257 
00258         p->max_trans_reply = 0;
00259         
00260         fstrcpy(p->name, pipe_name);
00261         
00262         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
00263                  pipe_name, i, pipes_open));
00264         
00265         chain_p = p;
00266         
00267         /* Iterate over p_it as a temp variable, to display all open pipes */ 
00268         for (p_it = Pipes; p_it; p_it = p_it->next) {
00269                 DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum));  
00270         }
00271 
00272         return chain_p;
00273 }
00274 
00275 /****************************************************************************
00276  Make an internal namedpipes structure
00277 ****************************************************************************/
00278 
00279 static void *make_internal_rpc_pipe_p(char *pipe_name, 
00280                               connection_struct *conn, uint16 vuid)
00281 {
00282         pipes_struct *p;
00283         user_struct *vuser = get_valid_user_struct(vuid);
00284 
00285         DEBUG(4,("Create pipe requested %s\n", pipe_name));
00286 
00287         if (!vuser && vuid != UID_FIELD_INVALID) {
00288                 DEBUG(0,("ERROR! vuid %d did not map to a valid vuser struct!\n", vuid));
00289                 return NULL;
00290         }
00291 
00292         p = SMB_MALLOC_P(pipes_struct);
00293 
00294         if (!p) {
00295                 DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
00296                 return NULL;
00297         }
00298 
00299         ZERO_STRUCTP(p);
00300 
00301         if ((p->mem_ctx = talloc_init("pipe %s %p", pipe_name, p)) == NULL) {
00302                 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
00303                 SAFE_FREE(p);
00304                 return NULL;
00305         }
00306 
00307         if ((p->pipe_state_mem_ctx = talloc_init("pipe_state %s %p", pipe_name, p)) == NULL) {
00308                 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
00309                 talloc_destroy(p->mem_ctx);
00310                 SAFE_FREE(p);
00311                 return NULL;
00312         }
00313 
00314         if (!init_pipe_handle_list(p, pipe_name)) {
00315                 DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
00316                 talloc_destroy(p->mem_ctx);
00317                 talloc_destroy(p->pipe_state_mem_ctx);
00318                 SAFE_FREE(p);
00319                 return NULL;
00320         }
00321 
00322         /*
00323          * Initialize the incoming RPC data buffer with one PDU worth of memory.
00324          * We cheat here and say we're marshalling, as we intend to add incoming
00325          * data directly into the prs_struct and we want it to auto grow. We will
00326          * change the type to UNMARSALLING before processing the stream.
00327          */
00328 
00329         if(!prs_init(&p->in_data.data, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
00330                 DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
00331                 talloc_destroy(p->mem_ctx);
00332                 talloc_destroy(p->pipe_state_mem_ctx);
00333                 close_policy_by_pipe(p);
00334                 SAFE_FREE(p);
00335                 return NULL;
00336         }
00337 
00338         DLIST_ADD(InternalPipes, p);
00339 
00340         p->conn = conn;
00341 
00342         p->vuid  = vuid;
00343 
00344         p->endian = RPC_LITTLE_ENDIAN;
00345 
00346         ZERO_STRUCT(p->pipe_user);
00347 
00348         p->pipe_user.ut.uid = (uid_t)-1;
00349         p->pipe_user.ut.gid = (gid_t)-1;
00350         
00351         /* Store the session key and NT_TOKEN */
00352         if (vuser) {
00353                 p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
00354                 p->pipe_user.nt_user_token = dup_nt_token(
00355                         NULL, vuser->nt_user_token);
00356         }
00357 
00358         /*
00359          * Initialize the outgoing RPC data buffer with no memory.
00360          */     
00361         prs_init(&p->out_data.rdata, 0, p->mem_ctx, MARSHALL);
00362         
00363         fstrcpy(p->name, pipe_name);
00364         
00365         DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
00366                  pipe_name, pipes_open));
00367 
00368         return (void*)p;
00369 }
00370 
00371 /****************************************************************************
00372  Sets the fault state on incoming packets.
00373 ****************************************************************************/
00374 
00375 static void set_incoming_fault(pipes_struct *p)
00376 {
00377         prs_mem_free(&p->in_data.data);
00378         p->in_data.pdu_needed_len = 0;
00379         p->in_data.pdu_received_len = 0;
00380         p->fault_state = True;
00381         DEBUG(10,("set_incoming_fault: Setting fault state on pipe %s : vuid = 0x%x\n",
00382                 p->name, p->vuid ));
00383 }
00384 
00385 /****************************************************************************
00386  Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
00387 ****************************************************************************/
00388 
00389 static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
00390 {
00391         size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
00392 
00393         DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
00394                         (unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
00395                         (unsigned int)p->in_data.pdu_received_len ));
00396 
00397         memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
00398         p->in_data.pdu_received_len += len_needed_to_complete_hdr;
00399 
00400         return (ssize_t)len_needed_to_complete_hdr;
00401 }
00402 
00403 /****************************************************************************
00404  Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
00405 ****************************************************************************/
00406 
00407 static ssize_t unmarshall_rpc_header(pipes_struct *p)
00408 {
00409         /*
00410          * Unmarshall the header to determine the needed length.
00411          */
00412 
00413         prs_struct rpc_in;
00414 
00415         if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
00416                 DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
00417                 set_incoming_fault(p);
00418                 return -1;
00419         }
00420 
00421         prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);
00422         prs_set_endian_data( &rpc_in, p->endian);
00423 
00424         prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
00425                                         p->in_data.pdu_received_len, False);
00426 
00427         /*
00428          * Unmarshall the header as this will tell us how much
00429          * data we need to read to get the complete pdu.
00430          * This also sets the endian flag in rpc_in.
00431          */
00432 
00433         if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
00434                 DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
00435                 set_incoming_fault(p);
00436                 prs_mem_free(&rpc_in);
00437                 return -1;
00438         }
00439 
00440         /*
00441          * Validate the RPC header.
00442          */
00443 
00444         if(p->hdr.major != 5 && p->hdr.minor != 0) {
00445                 DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
00446                 set_incoming_fault(p);
00447                 prs_mem_free(&rpc_in);
00448                 return -1;
00449         }
00450 
00451         /*
00452          * If there's not data in the incoming buffer this should be the start of a new RPC.
00453          */
00454 
00455         if(prs_offset(&p->in_data.data) == 0) {
00456 
00457                 /*
00458                  * AS/U doesn't set FIRST flag in a BIND packet it seems.
00459                  */
00460 
00461                 if ((p->hdr.pkt_type == RPC_REQUEST) && !(p->hdr.flags & RPC_FLG_FIRST)) {
00462                         /*
00463                          * Ensure that the FIRST flag is set. If not then we have
00464                          * a stream missmatch.
00465                          */
00466 
00467                         DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
00468                         set_incoming_fault(p);
00469                         prs_mem_free(&rpc_in);
00470                         return -1;
00471                 }
00472 
00473                 /*
00474                  * If this is the first PDU then set the endianness
00475                  * flag in the pipe. We will need this when parsing all
00476                  * data in this RPC.
00477                  */
00478 
00479                 p->endian = rpc_in.bigendian_data;
00480 
00481                 DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
00482                                 p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));
00483 
00484         } else {
00485 
00486                 /*
00487                  * If this is *NOT* the first PDU then check the endianness
00488                  * flag in the pipe is the same as that in the PDU.
00489                  */
00490 
00491                 if (p->endian != rpc_in.bigendian_data) {
00492                         DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
00493                         set_incoming_fault(p);
00494                         prs_mem_free(&rpc_in);
00495                         return -1;
00496                 }
00497         }
00498 
00499         /*
00500          * Ensure that the pdu length is sane.
00501          */
00502 
00503         if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
00504                 DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
00505                 set_incoming_fault(p);
00506                 prs_mem_free(&rpc_in);
00507                 return -1;
00508         }
00509 
00510         DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
00511                         (unsigned int)p->hdr.flags ));
00512 
00513         p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
00514 
00515         prs_mem_free(&rpc_in);
00516 
00517         return 0; /* No extra data processed. */
00518 }
00519 
00520 /****************************************************************************
00521  Call this to free any talloc'ed memory. Do this before and after processing
00522  a complete PDU.
00523 ****************************************************************************/
00524 
00525 static void free_pipe_context(pipes_struct *p)
00526 {
00527         if (p->mem_ctx) {
00528                 DEBUG(3,("free_pipe_context: destroying talloc pool of size "
00529                          "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));
00530                 talloc_free_children(p->mem_ctx);
00531         } else {
00532                 p->mem_ctx = talloc_init("pipe %s %p", p->name, p);
00533                 if (p->mem_ctx == NULL) {
00534                         p->fault_state = True;
00535                 }
00536         }
00537 }
00538 
00539 /****************************************************************************
00540  Processes a request pdu. This will do auth processing if needed, and
00541  appends the data into the complete stream if the LAST flag is not set.
00542 ****************************************************************************/
00543 
00544 static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
00545 {
00546         uint32 ss_padding_len = 0;
00547         size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
00548                                 (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
00549 
00550         if(!p->pipe_bound) {
00551                 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
00552                 set_incoming_fault(p);
00553                 return False;
00554         }
00555 
00556         /*
00557          * Check if we need to do authentication processing.
00558          * This is only done on requests, not binds.
00559          */
00560 
00561         /*
00562          * Read the RPC request header.
00563          */
00564 
00565         if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
00566                 DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
00567                 set_incoming_fault(p);
00568                 return False;
00569         }
00570 
00571         switch(p->auth.auth_type) {
00572                 case PIPE_AUTH_TYPE_NONE:
00573                         break;
00574 
00575                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
00576                 case PIPE_AUTH_TYPE_NTLMSSP:
00577                 {
00578                         NTSTATUS status;
00579                         if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
00580                                 DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
00581                                 DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
00582                                 set_incoming_fault(p);
00583                                 return False;
00584                         }
00585                         break;
00586                 }
00587 
00588                 case PIPE_AUTH_TYPE_SCHANNEL:
00589                         if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
00590                                 DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
00591                                 set_incoming_fault(p);
00592                                 return False;
00593                         }
00594                         break;
00595 
00596                 default:
00597                         DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
00598                         set_incoming_fault(p);
00599                         return False;
00600         }
00601 
00602         /* Now we've done the sign/seal we can remove any padding data. */
00603         if (data_len > ss_padding_len) {
00604                 data_len -= ss_padding_len;
00605         }
00606 
00607         /*
00608          * Check the data length doesn't go over the 15Mb limit.
00609          * increased after observing a bug in the Windows NT 4.0 SP6a
00610          * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
00611          * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
00612          */
00613         
00614         if(prs_offset(&p->in_data.data) + data_len > 15*1024*1024) {
00615                 DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
00616                                 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
00617                 set_incoming_fault(p);
00618                 return False;
00619         }
00620 
00621         /*
00622          * Append the data portion into the buffer and return.
00623          */
00624 
00625         if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
00626                 DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
00627                                 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
00628                 set_incoming_fault(p);
00629                 return False;
00630         }
00631 
00632         if(p->hdr.flags & RPC_FLG_LAST) {
00633                 BOOL ret = False;
00634                 /*
00635                  * Ok - we finally have a complete RPC stream.
00636                  * Call the rpc command to process it.
00637                  */
00638 
00639                 /*
00640                  * Ensure the internal prs buffer size is *exactly* the same
00641                  * size as the current offset.
00642                  */
00643 
00644                 if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
00645                         DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
00646                         set_incoming_fault(p);
00647                         return False;
00648                 }
00649 
00650                 /*
00651                  * Set the parse offset to the start of the data and set the
00652                  * prs_struct to UNMARSHALL.
00653                  */
00654 
00655                 prs_set_offset(&p->in_data.data, 0);
00656                 prs_switch_type(&p->in_data.data, UNMARSHALL);
00657 
00658                 /*
00659                  * Process the complete data stream here.
00660                  */
00661 
00662                 free_pipe_context(p);
00663 
00664                 if(pipe_init_outgoing_data(p)) {
00665                         ret = api_pipe_request(p);
00666                 }
00667 
00668                 free_pipe_context(p);
00669 
00670                 /*
00671                  * We have consumed the whole data stream. Set back to
00672                  * marshalling and set the offset back to the start of
00673                  * the buffer to re-use it (we could also do a prs_mem_free()
00674                  * and then re_init on the next start of PDU. Not sure which
00675                  * is best here.... JRA.
00676                  */
00677 
00678                 prs_switch_type(&p->in_data.data, MARSHALL);
00679                 prs_set_offset(&p->in_data.data, 0);
00680                 return ret;
00681         }
00682 
00683         return True;
00684 }
00685 
00686 /****************************************************************************
00687  Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
00688  already been parsed and stored in p->hdr.
00689 ****************************************************************************/
00690 
00691 static void process_complete_pdu(pipes_struct *p)
00692 {
00693         prs_struct rpc_in;
00694         size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;
00695         char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];
00696         BOOL reply = False;
00697 
00698         if(p->fault_state) {
00699                 DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
00700                         p->name ));
00701                 set_incoming_fault(p);
00702                 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
00703                 return;
00704         }
00705 
00706         prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);
00707 
00708         /*
00709          * Ensure we're using the corrent endianness for both the 
00710          * RPC header flags and the raw data we will be reading from.
00711          */
00712 
00713         prs_set_endian_data( &rpc_in, p->endian);
00714         prs_set_endian_data( &p->in_data.data, p->endian);
00715 
00716         prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
00717 
00718         DEBUG(10,("process_complete_pdu: processing packet type %u\n",
00719                         (unsigned int)p->hdr.pkt_type ));
00720 
00721         switch (p->hdr.pkt_type) {
00722                 case RPC_REQUEST:
00723                         reply = process_request_pdu(p, &rpc_in);
00724                         break;
00725 
00726                 case RPC_PING: /* CL request - ignore... */
00727                         DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
00728                                 (unsigned int)p->hdr.pkt_type, p->name));
00729                         break;
00730 
00731                 case RPC_RESPONSE: /* No responses here. */
00732                         DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n",
00733                                 p->name ));
00734                         break;
00735 
00736                 case RPC_FAULT:
00737                 case RPC_WORKING: /* CL request - reply to a ping when a call in process. */
00738                 case RPC_NOCALL: /* CL - server reply to a ping call. */
00739                 case RPC_REJECT:
00740                 case RPC_ACK:
00741                 case RPC_CL_CANCEL:
00742                 case RPC_FACK:
00743                 case RPC_CANCEL_ACK:
00744                         DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
00745                                 (unsigned int)p->hdr.pkt_type, p->name));
00746                         break;
00747 
00748                 case RPC_BIND:
00749                         /*
00750                          * We assume that a pipe bind is only in one pdu.
00751                          */
00752                         if(pipe_init_outgoing_data(p)) {
00753                                 reply = api_pipe_bind_req(p, &rpc_in);
00754                         }
00755                         break;
00756 
00757                 case RPC_BINDACK:
00758                 case RPC_BINDNACK:
00759                         DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n",
00760                                 (unsigned int)p->hdr.pkt_type, p->name));
00761                         break;
00762 
00763 
00764                 case RPC_ALTCONT:
00765                         /*
00766                          * We assume that a pipe bind is only in one pdu.
00767                          */
00768                         if(pipe_init_outgoing_data(p)) {
00769                                 reply = api_pipe_alter_context(p, &rpc_in);
00770                         }
00771                         break;
00772 
00773                 case RPC_ALTCONTRESP:
00774                         DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n",
00775                                 p->name));
00776                         break;
00777 
00778                 case RPC_AUTH3:
00779                         /*
00780                          * The third packet in an NTLMSSP auth exchange.
00781                          */
00782                         if(pipe_init_outgoing_data(p)) {
00783                                 reply = api_pipe_bind_auth3(p, &rpc_in);
00784                         }
00785                         break;
00786 
00787                 case RPC_SHUTDOWN:
00788                         DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n",
00789                                 p->name));
00790                         break;
00791 
00792                 case RPC_CO_CANCEL:
00793                         /* For now just free all client data and continue processing. */
00794                         DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
00795                         /* As we never do asynchronous RPC serving, we can never cancel a
00796                            call (as far as I know). If we ever did we'd have to send a cancel_ack
00797                            reply. For now, just free all client data and continue processing. */
00798                         reply = True;
00799                         break;
00800 #if 0
00801                         /* Enable this if we're doing async rpc. */
00802                         /* We must check the call-id matches the outstanding callid. */
00803                         if(pipe_init_outgoing_data(p)) {
00804                                 /* Send a cancel_ack PDU reply. */
00805                                 /* We should probably check the auth-verifier here. */
00806                                 reply = setup_cancel_ack_reply(p, &rpc_in);
00807                         }
00808                         break;
00809 #endif
00810 
00811                 case RPC_ORPHANED:
00812                         /* We should probably check the auth-verifier here.
00813                            For now just free all client data and continue processing. */
00814                         DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
00815                         reply = True;
00816                         break;
00817 
00818                 default:
00819                         DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
00820                         break;
00821         }
00822 
00823         /* Reset to little endian. Probably don't need this but it won't hurt. */
00824         prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN);
00825 
00826         if (!reply) {
00827                 DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));
00828                 set_incoming_fault(p);
00829                 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
00830                 prs_mem_free(&rpc_in);
00831         } else {
00832                 /*
00833                  * Reset the lengths. We're ready for a new pdu.
00834                  */
00835                 p->in_data.pdu_needed_len = 0;
00836                 p->in_data.pdu_received_len = 0;
00837         }
00838 
00839         prs_mem_free(&rpc_in);
00840 }
00841 
00842 /****************************************************************************
00843  Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
00844 ****************************************************************************/
00845 
00846 static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
00847 {
00848         size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
00849 
00850         DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
00851                 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
00852                 (unsigned int)n ));
00853 
00854         if(data_to_copy == 0) {
00855                 /*
00856                  * This is an error - data is being received and there is no
00857                  * space in the PDU. Free the received data and go into the fault state.
00858                  */
00859                 DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
00860 incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
00861                 set_incoming_fault(p);
00862                 return -1;
00863         }
00864 
00865         /*
00866          * If we have no data already, wait until we get at least a RPC_HEADER_LEN
00867          * number of bytes before we can do anything.
00868          */
00869 
00870         if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
00871                 /*
00872                  * Always return here. If we have more data then the RPC_HEADER
00873                  * will be processed the next time around the loop.
00874                  */
00875                 return fill_rpc_header(p, data, data_to_copy);
00876         }
00877 
00878         /*
00879          * At this point we know we have at least an RPC_HEADER_LEN amount of data
00880          * stored in current_in_pdu.
00881          */
00882 
00883         /*
00884          * If pdu_needed_len is zero this is a new pdu. 
00885          * Unmarshall the header so we know how much more
00886          * data we need, then loop again.
00887          */
00888 
00889         if(p->in_data.pdu_needed_len == 0) {
00890                 ssize_t rret = unmarshall_rpc_header(p);
00891                 if (rret == -1 || p->in_data.pdu_needed_len > 0) {
00892                         return rret;
00893                 }
00894                 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists
00895                    of an RPC_HEADER only. This is a RPC_SHUTDOWN, RPC_CO_CANCEL or RPC_ORPHANED
00896                    pdu type. Deal with this in process_complete_pdu(). */
00897         }
00898 
00899         /*
00900          * Ok - at this point we have a valid RPC_HEADER in p->hdr.
00901          * Keep reading until we have a full pdu.
00902          */
00903 
00904         data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
00905 
00906         /*
00907          * Copy as much of the data as we need into the current_in_pdu buffer.
00908          * pdu_needed_len becomes zero when we have a complete pdu.
00909          */
00910 
00911         memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
00912         p->in_data.pdu_received_len += data_to_copy;
00913         p->in_data.pdu_needed_len -= data_to_copy;
00914 
00915         /*
00916          * Do we have a complete PDU ?
00917          * (return the number of bytes handled in the call)
00918          */
00919 
00920         if(p->in_data.pdu_needed_len == 0) {
00921                 process_complete_pdu(p);
00922                 return data_to_copy;
00923         }
00924 
00925         DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
00926                 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
00927 
00928         return (ssize_t)data_to_copy;
00929 }
00930 
00931 /****************************************************************************
00932  Accepts incoming data on an rpc pipe.
00933 ****************************************************************************/
00934 
00935 ssize_t write_to_pipe(smb_np_struct *p, char *data, size_t n)
00936 {
00937         DEBUG(6,("write_to_pipe: %x", p->pnum));
00938 
00939         DEBUG(6,(" name: %s open: %s len: %d\n",
00940                  p->name, BOOLSTR(p->open), (int)n));
00941 
00942         dump_data(50, data, n);
00943 
00944         return p->namedpipe_write(p->np_state, data, n);
00945 }
00946 
00947 /****************************************************************************
00948  Accepts incoming data on an internal rpc pipe.
00949 ****************************************************************************/
00950 
00951 static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n)
00952 {
00953         pipes_struct *p = (pipes_struct*)np_conn;
00954         size_t data_left = n;
00955 
00956         while(data_left) {
00957                 ssize_t data_used;
00958 
00959                 DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
00960 
00961                 data_used = process_incoming_data(p, data, data_left);
00962 
00963                 DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
00964 
00965                 if(data_used < 0) {
00966                         return -1;
00967                 }
00968 
00969                 data_left -= data_used;
00970                 data += data_used;
00971         }       
00972 
00973         return n;
00974 }
00975 
00976 /****************************************************************************
00977  Replies to a request to read data from a pipe.
00978 
00979  Headers are interspersed with the data at PDU intervals. By the time
00980  this function is called, the start of the data could possibly have been
00981  read by an SMBtrans (file_offset != 0).
00982 
00983  Calling create_rpc_reply() here is a hack. The data should already
00984  have been prepared into arrays of headers + data stream sections.
00985 ****************************************************************************/
00986 
00987 ssize_t read_from_pipe(smb_np_struct *p, char *data, size_t n,
00988                 BOOL *is_data_outstanding)
00989 {
00990         if (!p || !p->open) {
00991                 DEBUG(0,("read_from_pipe: pipe not open\n"));
00992                 return -1;              
00993         }
00994 
00995         DEBUG(6,("read_from_pipe: %x", p->pnum));
00996 
00997         return p->namedpipe_read(p->np_state, data, n, is_data_outstanding);
00998 }
00999 
01000 /****************************************************************************
01001  Replies to a request to read data from a pipe.
01002 
01003  Headers are interspersed with the data at PDU intervals. By the time
01004  this function is called, the start of the data could possibly have been
01005  read by an SMBtrans (file_offset != 0).
01006 
01007  Calling create_rpc_reply() here is a hack. The data should already
01008  have been prepared into arrays of headers + data stream sections.
01009 ****************************************************************************/
01010 
01011 static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,
01012                 BOOL *is_data_outstanding)
01013 {
01014         pipes_struct *p = (pipes_struct*)np_conn;
01015         uint32 pdu_remaining = 0;
01016         ssize_t data_returned = 0;
01017 
01018         if (!p) {
01019                 DEBUG(0,("read_from_pipe: pipe not open\n"));
01020                 return -1;              
01021         }
01022 
01023         DEBUG(6,(" name: %s len: %u\n", p->name, (unsigned int)n));
01024 
01025         /*
01026          * We cannot return more than one PDU length per
01027          * read request.
01028          */
01029 
01030         /*
01031          * This condition should result in the connection being closed.  
01032          * Netapp filers seem to set it to 0xffff which results in domain
01033          * authentications failing.  Just ignore it so things work.
01034          */
01035 
01036         if(n > RPC_MAX_PDU_FRAG_LEN) {
01037                 DEBUG(5,("read_from_pipe: too large read (%u) requested on \
01038 pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN ));
01039         }
01040 
01041         /*
01042          * Determine if there is still data to send in the
01043          * pipe PDU buffer. Always send this first. Never
01044          * send more than is left in the current PDU. The
01045          * client should send a new read request for a new
01046          * PDU.
01047          */
01048 
01049         if((pdu_remaining = p->out_data.current_pdu_len - p->out_data.current_pdu_sent) > 0) {
01050                 data_returned = (ssize_t)MIN(n, pdu_remaining);
01051 
01052                 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \
01053 returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, 
01054                         (unsigned int)p->out_data.current_pdu_sent, (int)data_returned));
01055 
01056                 memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned);
01057                 p->out_data.current_pdu_sent += (uint32)data_returned;
01058                 goto out;
01059         }
01060 
01061         /*
01062          * At this point p->current_pdu_len == p->current_pdu_sent (which
01063          * may of course be zero if this is the first return fragment.
01064          */
01065 
01066         DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \
01067 = %u, prs_offset(&p->out_data.rdata) = %u.\n",
01068                 p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) ));
01069 
01070         if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
01071                 /*
01072                  * We have sent all possible data, return 0.
01073                  */
01074                 data_returned = 0;
01075                 goto out;
01076         }
01077 
01078         /*
01079          * We need to create a new PDU from the data left in p->rdata.
01080          * Create the header/data/footers. This also sets up the fields
01081          * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
01082          * and stores the outgoing PDU in p->current_pdu.
01083          */
01084 
01085         if(!create_next_pdu(p)) {
01086                 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", p->name));
01087                 return -1;
01088         }
01089 
01090         data_returned = MIN(n, p->out_data.current_pdu_len);
01091 
01092         memcpy( data, p->out_data.current_pdu, (size_t)data_returned);
01093         p->out_data.current_pdu_sent += (uint32)data_returned;
01094 
01095   out:
01096 
01097         (*is_data_outstanding) = p->out_data.current_pdu_len > n;
01098         return data_returned;
01099 }
01100 
01101 /****************************************************************************
01102  Wait device state on a pipe. Exactly what this is for is unknown...
01103 ****************************************************************************/
01104 
01105 BOOL wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority)
01106 {
01107         if (p == NULL) {
01108                 return False;
01109         }
01110 
01111         if (p->open) {
01112                 DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
01113                          priority, p->name));
01114 
01115                 p->priority = priority;
01116                 
01117                 return True;
01118         } 
01119 
01120         DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n",
01121                  priority, p->name));
01122         return False;
01123 }
01124 
01125 
01126 /****************************************************************************
01127  Set device state on a pipe. Exactly what this is for is unknown...
01128 ****************************************************************************/
01129 
01130 BOOL set_rpc_pipe_hnd_state(smb_np_struct *p, uint16 device_state)
01131 {
01132         if (p == NULL) {
01133                 return False;
01134         }
01135 
01136         if (p->open) {
01137                 DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
01138                          device_state, p->name));
01139 
01140                 p->device_state = device_state;
01141                 
01142                 return True;
01143         } 
01144 
01145         DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n",
01146                  device_state, p->name));
01147         return False;
01148 }
01149 
01150 
01151 /****************************************************************************
01152  Close an rpc pipe.
01153 ****************************************************************************/
01154 
01155 BOOL close_rpc_pipe_hnd(smb_np_struct *p)
01156 {
01157         if (!p) {
01158                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
01159                 return False;
01160         }
01161 
01162         p->namedpipe_close(p->np_state);
01163 
01164         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
01165 
01166         pipes_open--;
01167 
01168         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
01169                  p->name, p->pnum, pipes_open));  
01170 
01171         DLIST_REMOVE(Pipes, p);
01172         
01173         /* Remove from pipe open db */
01174         
01175         if ( !delete_pipe_opendb( p ) ) {
01176                 DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s "
01177                         "pipe from open db.\n", p->name));
01178         }
01179 
01180         ZERO_STRUCTP(p);
01181 
01182         SAFE_FREE(p);
01183 
01184         return True;
01185 }
01186 
01187 /****************************************************************************
01188  Close all pipes on a connection.
01189 ****************************************************************************/
01190 
01191 void pipe_close_conn(connection_struct *conn)
01192 {
01193         smb_np_struct *p, *next;
01194 
01195         for (p=Pipes;p;p=next) {
01196                 next = p->next;
01197                 if (p->conn == conn) {
01198                         close_rpc_pipe_hnd(p);
01199                 }
01200         }
01201 }
01202 
01203 /****************************************************************************
01204  Close an rpc pipe.
01205 ****************************************************************************/
01206 
01207 static BOOL close_internal_rpc_pipe_hnd(void *np_conn)
01208 {
01209         pipes_struct *p = (pipes_struct *)np_conn;
01210         if (!p) {
01211                 DEBUG(0,("Invalid pipe in close_internal_rpc_pipe_hnd\n"));
01212                 return False;
01213         }
01214 
01215         prs_mem_free(&p->out_data.rdata);
01216         prs_mem_free(&p->in_data.data);
01217 
01218         if (p->auth.auth_data_free_func) {
01219                 (*p->auth.auth_data_free_func)(&p->auth);
01220         }
01221 
01222         if (p->mem_ctx) {
01223                 talloc_destroy(p->mem_ctx);
01224         }
01225 
01226         if (p->pipe_state_mem_ctx) {
01227                 talloc_destroy(p->pipe_state_mem_ctx);
01228         }
01229 
01230         free_pipe_rpc_context( p->contexts );
01231 
01232         /* Free the handles database. */
01233         close_policy_by_pipe(p);
01234 
01235         TALLOC_FREE(p->pipe_user.nt_user_token);
01236         data_blob_free(&p->session_key);
01237         SAFE_FREE(p->pipe_user.ut.groups);
01238 
01239         DLIST_REMOVE(InternalPipes, p);
01240 
01241         ZERO_STRUCTP(p);
01242 
01243         SAFE_FREE(p);
01244         
01245         return True;
01246 }
01247 
01248 /****************************************************************************
01249  Find an rpc pipe given a pipe handle in a buffer and an offset.
01250 ****************************************************************************/
01251 
01252 smb_np_struct *get_rpc_pipe_p(char *buf, int where)
01253 {
01254         int pnum = SVAL(buf,where);
01255 
01256         if (chain_p) {
01257                 return chain_p;
01258         }
01259 
01260         return get_rpc_pipe(pnum);
01261 }
01262 
01263 /****************************************************************************
01264  Find an rpc pipe given a pipe handle.
01265 ****************************************************************************/
01266 
01267 smb_np_struct *get_rpc_pipe(int pnum)
01268 {
01269         smb_np_struct *p;
01270 
01271         DEBUG(4,("search for pipe pnum=%x\n", pnum));
01272 
01273         for (p=Pipes;p;p=p->next) {
01274                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
01275                           p->name, p->pnum, pipes_open));  
01276         }
01277 
01278         for (p=Pipes;p;p=p->next) {
01279                 if (p->pnum == pnum) {
01280                         chain_p = p;
01281                         return p;
01282                 }
01283         }
01284 
01285         return NULL;
01286 }

Sambaに対してSat Aug 29 21:23:20 2009に生成されました。  doxygen 1.4.7