3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1998,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8 * Copyright (C) Jeremy Allison 1999.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define PIPE "\\PIPE\\"
30 #define PIPELEN strlen(PIPE)
32 extern int DEBUGLEVEL;
33 static pipes_struct *chain_p;
34 static int pipes_open;
36 #ifndef MAX_OPEN_PIPES
37 #define MAX_OPEN_PIPES 64
40 static pipes_struct *Pipes;
41 static struct bitmap *bmap;
43 /* this must be larger than the sum of the open files and directories */
44 static int pipe_handle_offset;
46 /****************************************************************************
47 Set the pipe_handle_offset. Called from smbd/files.c
48 ****************************************************************************/
50 void set_pipe_handle_offset(int max_open_files)
52 if(max_open_files < 0x7000)
53 pipe_handle_offset = 0x7000;
55 pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
58 /****************************************************************************
59 Reset pipe chain handle number.
60 ****************************************************************************/
61 void reset_chain_p(void)
66 /****************************************************************************
67 Initialise pipe handle states.
68 ****************************************************************************/
70 void init_rpc_pipe_hnd(void)
72 bmap = bitmap_allocate(MAX_OPEN_PIPES);
74 exit_server("out of memory in init_rpc_pipe_hnd\n");
77 /****************************************************************************
78 Initialise an outgoing packet.
79 ****************************************************************************/
81 BOOL pipe_init_outgoing_data( pipes_struct *p)
84 memset(p->current_pdu, '\0', sizeof(p->current_pdu));
86 /* Free any memory in the current return data buffer. */
87 prs_mem_free(&p->rdata);
90 * Initialize the outgoing RPC data buffer.
91 * we will use this as the raw data area for replying to rpc requests.
93 if(!prs_init(&p->rdata, 1024, 4, MARSHALL)) {
94 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
98 /* Reset the offset counters. */
99 p->data_sent_length = 0;
100 p->current_pdu_len = 0;
101 p->current_pdu_sent = 0;
106 /****************************************************************************
107 Find first available pipe slot.
108 ****************************************************************************/
110 pipes_struct *open_rpc_pipe_p(char *pipe_name,
111 connection_struct *conn, uint16 vuid)
115 static int next_pipe;
117 DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
118 pipe_name, pipes_open));
120 /* not repeating pipe numbers makes it easier to track things in
121 log files and prevents client bugs where pipe numbers are reused
122 over connection restarts */
124 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
126 i = bitmap_find(bmap, next_pipe);
129 DEBUG(0,("ERROR! Out of pipe structures\n"));
133 next_pipe = (i+1) % MAX_OPEN_PIPES;
135 for (p = Pipes; p; p = p->next)
136 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
138 p = (pipes_struct *)malloc(sizeof(*p));
145 * Initialize the RPC and PDU data buffers with no memory.
147 prs_init(&p->rdata, 0, 4, MARSHALL);
152 i += pipe_handle_offset;
164 p->max_trans_reply = 0;
166 p->ntlmssp_chal_flags = 0;
167 p->ntlmssp_auth_validated = False;
168 p->ntlmssp_auth_requested = False;
170 p->current_pdu_len = 0;
171 p->current_pdu_sent = 0;
172 p->data_sent_length = 0;
177 fstrcpy(p->name, pipe_name);
179 DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
180 pipe_name, i, pipes_open));
184 /* OVERWRITE p as a temp variable, to display all open pipes */
185 for (p = Pipes; p; p = p->next)
186 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
192 /****************************************************************************
193 Accepts incoming data on an rpc pipe.
195 This code is probably incorrect at the moment. The problem is
196 that the rpc request shouldn't really be executed until all the
197 data needed for it is received. This currently assumes that each
198 SMBwrite or SMBwriteX contains all the data needed for an rpc
200 ****************************************************************************/
202 ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n)
204 DEBUG(6,("write_pipe: %x", p->pnum));
206 DEBUG(6,("name: %s open: %s len: %d",
207 p->name, BOOLSTR(p->open), (int)n));
209 dump_data(50, data, n);
211 return rpc_command(p, data, (int)n) ? ((ssize_t)n) : -1;
215 /****************************************************************************
216 Replyies to a request to read data from a pipe.
218 Headers are interspersed with the data at PDU intervals. By the time
219 this function is called, the start of the data could possibly have been
220 read by an SMBtrans (file_offset != 0).
222 Calling create_rpc_reply() here is a hack. The data should already
223 have been prepared into arrays of headers + data stream sections.
225 ****************************************************************************/
227 int read_from_pipe(pipes_struct *p, char *data, int n)
229 uint32 pdu_remaining = 0;
230 int data_returned = 0;
232 if (!p || !p->open) {
233 DEBUG(0,("read_from_pipe: pipe not open\n"));
237 DEBUG(6,("read_from_pipe: %x", p->pnum));
239 DEBUG(6,("name: %s len: %d\n", p->name, n));
242 * We cannot return more than one PDU length per
246 if(n > MAX_PDU_FRAG_LEN) {
247 DEBUG(0,("read_from_pipe: loo large read (%d) requested on pipe %s. We can \
248 only service %d sized reads.\n", n, p->name, MAX_PDU_FRAG_LEN ));
253 * Determine if there is still data to send in the
254 * pipe PDU buffer. Always send this first. Never
255 * send more than is left in the current PDU. The
256 * client should send a new read request for a new
260 if((pdu_remaining = p->current_pdu_len - p->current_pdu_sent) > 0) {
261 data_returned = MIN(n, pdu_remaining);
263 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \
264 returning %d bytes.\n", p->name, (unsigned int)p->current_pdu_len,
265 (unsigned int)p->current_pdu_sent, (int)data_returned));
267 memcpy( data, &p->current_pdu[p->current_pdu_sent], (size_t)data_returned);
268 p->current_pdu_sent += (uint32)data_returned;
269 return data_returned;
273 * At this point p->current_pdu_len == p->current_pdu_sent (which
274 * may of course be zero if this is the first return fragment.
277 DEBUG(10,("read_from_pipe: %s: data_sent_length = %u, prs_offset(&p->rdata) = %u.\n",
278 p->name, (unsigned int)p->data_sent_length, (unsigned int)prs_offset(&p->rdata) ));
280 if(p->data_sent_length >= prs_offset(&p->rdata)) {
282 * We have sent all possible data. Return 0.
288 * We need to create a new PDU from the data left in p->rdata.
289 * Create the header/data/footers. This also sets up the fields
290 * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
291 * and stores the outgoing PDU in p->current_pdu.
294 if(!create_next_pdu(p)) {
295 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
300 data_returned = MIN(n, p->current_pdu_len);
302 memcpy( data, p->current_pdu, (size_t)data_returned);
303 p->current_pdu_sent += (uint32)data_returned;
304 return data_returned;
307 /****************************************************************************
308 Wait device state on a pipe. Exactly what this is for is unknown...
309 ****************************************************************************/
311 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
317 DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
320 p->priority = priority;
325 DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n",
331 /****************************************************************************
332 Set device state on a pipe. Exactly what this is for is unknown...
333 ****************************************************************************/
335 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
341 DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
342 device_state, p->name));
344 p->device_state = device_state;
349 DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n",
350 device_state, p->name));
355 /****************************************************************************
357 ****************************************************************************/
359 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
362 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
366 prs_mem_free(&p->rdata);
368 bitmap_clear(bmap, p->pnum - pipe_handle_offset);
372 DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n",
373 p->name, p->pnum, pipes_open));
375 DLIST_REMOVE(Pipes, p);
384 /****************************************************************************
385 Find an rpc pipe given a pipe handle in a buffer and an offset.
386 ****************************************************************************/
388 pipes_struct *get_rpc_pipe_p(char *buf, int where)
390 int pnum = SVAL(buf,where);
395 return get_rpc_pipe(pnum);
398 /****************************************************************************
399 Find an rpc pipe given a pipe handle.
400 ****************************************************************************/
402 pipes_struct *get_rpc_pipe(int pnum)
406 DEBUG(4,("search for pipe pnum=%x\n", pnum));
408 for (p=Pipes;p;p=p->next)
409 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n",
410 p->name, p->pnum, pipes_open));
412 for (p=Pipes;p;p=p->next) {
413 if (p->pnum == pnum) {