corrections to get data stream for 2nd and subsequent pdus copied from
[samba.git] / source / rpc_server / srv_pipe_hnd.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1998,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24
25 #include "includes.h"
26
27
28 #define PIPE            "\\PIPE\\"
29 #define PIPELEN         strlen(PIPE)
30
31 extern int DEBUGLEVEL;
32 static pipes_struct *chain_p;
33 static int pipes_open;
34
35 #ifndef MAX_OPEN_PIPES
36 #define MAX_OPEN_PIPES 64
37 #endif
38
39 static pipes_struct *Pipes;
40 static struct bitmap *bmap;
41
42 /* this must be larger than the sum of the open files and directories */
43 static int pipe_handle_offset;
44
45 /****************************************************************************
46  Set the pipe_handle_offset. Called from smbd/files.c
47 ****************************************************************************/
48
49 void set_pipe_handle_offset(int max_open_files)
50 {
51   if(max_open_files < 0x7000)
52     pipe_handle_offset = 0x7000;
53   else
54     pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
55 }
56
57 /****************************************************************************
58   reset pipe chain handle number
59 ****************************************************************************/
60 void reset_chain_p(void)
61 {
62         chain_p = NULL;
63 }
64
65 /****************************************************************************
66   initialise pipe handle states...
67 ****************************************************************************/
68 void init_rpc_pipe_hnd(void)
69 {
70         bmap = bitmap_allocate(MAX_OPEN_PIPES);
71         if (!bmap) {
72                 exit_server("out of memory in init_rpc_pipe_hnd\n");
73         }
74 }
75
76
77 /****************************************************************************
78   find first available file slot
79 ****************************************************************************/
80 pipes_struct *open_rpc_pipe_p(char *pipe_name, 
81                               connection_struct *conn, uint16 vuid)
82 {
83         int i;
84         pipes_struct *p;
85         static int next_pipe;
86
87         DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
88                  pipe_name, pipes_open));
89         
90         /* not repeating pipe numbers makes it easier to track things in 
91            log files and prevents client bugs where pipe numbers are reused
92            over connection restarts */
93         if (next_pipe == 0) {
94                 next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
95         }
96
97         i = bitmap_find(bmap, next_pipe);
98
99         if (i == -1) {
100                 DEBUG(0,("ERROR! Out of pipe structures\n"));
101                 return NULL;
102         }
103
104         next_pipe = (i+1) % MAX_OPEN_PIPES;
105
106         for (p = Pipes; p; p = p->next)
107         {
108                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
109         }
110
111         p = (pipes_struct *)malloc(sizeof(*p));
112         if (!p) return NULL;
113
114         ZERO_STRUCTP(p);
115         DLIST_ADD(Pipes, p);
116
117         bitmap_set(bmap, i);
118         i += pipe_handle_offset;
119
120         pipes_open++;
121
122         p->pnum = i;
123
124         p->open = True;
125         p->device_state = 0;
126         p->priority = 0;
127         p->conn = conn;
128         p->vuid  = vuid;
129         
130         p->rhdr.data  = NULL;
131         p->rdata.data = NULL;
132         p->rhdr.offset  = 0;
133         p->rdata.offset = 0;
134         
135         p->file_offset     = 0;
136         p->prev_pdu_file_offset = 0;
137         p->hdr_offsets     = 0;
138         
139         p->ntlmssp_validated = False;
140         p->ntlmssp_auth      = False;
141         
142         fstrcpy(p->name, pipe_name);
143         
144         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
145                  pipe_name, i, pipes_open));
146         
147         chain_p = p;
148         
149         /* OVERWRITE p as a temp variable, to display all open pipes */ 
150         for (p = Pipes; p; p = p->next)
151         {
152                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
153         }
154
155         return chain_p;
156 }
157
158
159 /****************************************************************************
160  writes data to a pipe.
161
162  SERIOUSLY ALPHA CODE!
163  ****************************************************************************/
164 ssize_t write_pipe(pipes_struct *p, char *data, size_t n)
165 {
166         prs_struct pd;
167         struct mem_buf data_buf;
168
169         DEBUG(6,("write_pipe: %x", p->pnum));
170
171         DEBUG(6,("name: %s open: %s len: %d",
172                  p->name, BOOLSTR(p->open), n));
173
174         dump_data(50, data, n);
175
176         /* fake up a data buffer from the write_pipe data parameters */
177         mem_create(&data_buf, data, 0, n, 0, False);
178         data_buf.offset.start = 0;
179         data_buf.offset.end   = n;
180
181         /* fake up a parsing structure */
182         pd.data = &data_buf;
183         pd.align = 4;
184         pd.io = True;
185         pd.offset = 0;
186
187         return rpc_command(p, &pd) ? ((ssize_t)n) : -1;
188 }
189
190
191 /****************************************************************************
192  reads data from a pipe.
193
194  headers are interspersed with the data at regular intervals.  by the time
195  this function is called, the start of the data could possibly have been
196  read by an SMBtrans (file_offset != 0).
197
198  calling create_rpc_reply() here is a fudge.  the data should already
199  have been prepared into arrays of headers + data stream sections.
200
201  ****************************************************************************/
202 int read_pipe(pipes_struct *p, char *data, uint32 pos, int n)
203 {
204         int num = 0;
205         int pdu_len = 0;
206         uint32 hdr_num = 0;
207         int pdu_data_sent; /* amount of current pdu already sent */
208         int data_pos; /* entire rpc data sent - no headers, no auth verifiers */
209         int this_pdu_data_pos;
210
211         DEBUG(6,("read_pipe: %x", p->pnum));
212
213         DEBUG(6,("name: %s open: %s pos: %d len: %d",
214                  p->name,
215                  BOOLSTR(p->open),
216                  pos, n));
217
218         if (!p || !p->open)
219         {
220                 DEBUG(6,("pipe not open\n"));
221                 return -1;              
222         }
223
224
225         if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
226             p->rhdr.data->data_used == 0)
227         {
228                 return 0;
229         }
230
231         DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
232                  p, p->file_offset, n));
233
234         /* the read request starts from where the SMBtrans2 left off. */
235         data_pos = p->file_offset - p->hdr_offsets;
236         this_pdu_data_pos = data_pos - p->prev_pdu_file_offset;
237         pdu_data_sent = p->file_offset - p->prev_pdu_file_offset;
238
239         if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
240         {
241                 /* intermediate fragment - possibility of another header */
242                 
243                 DEBUG(5,("read_pipe: frag_len: %d data_pos: %d pdu_data_sent: %d\n",
244                          p->hdr.frag_len, data_pos, pdu_data_sent));
245                 
246                 if (pdu_data_sent == 0)
247                 {
248                         DEBUG(6,("read_pipe: next fragment header\n"));
249
250                         /* this is subtracted from the total data bytes, later */
251                         hdr_num = 0x18;
252                         p->hdr_offsets += 0x18;
253                         data_pos -= 0x18;
254
255                         /* create and copy in a new header. */
256                         create_rpc_reply(p, data_pos, p->rdata.offset);
257                 }                       
258         }
259         
260         pdu_len = mem_buf_len(p->rhdr.data);
261         num = pdu_len - (int)this_pdu_data_pos;
262         
263         DEBUG(6,("read_pipe: pdu_len: %d num: %d n: %d\n", pdu_len, num, n));
264         
265         if (num > n) num = n;
266         if (num <= 0)
267         {
268                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
269                 return 0;
270         }
271
272         if (num < hdr_num)
273         {
274                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
275         }
276
277         mem_buf_copy(data, p->rhdr.data, pdu_data_sent, num);
278         
279         p->file_offset  += num;
280         pdu_data_sent  += num;
281         
282         if (hdr_num == 0x18 && num == 0x18)
283         {
284                 DEBUG(6,("read_pipe: just header read\n"));
285         }
286
287         if (pdu_data_sent == p->hdr.frag_len)
288         {
289                 DEBUG(6,("read_pipe: next fragment expected\n"));
290                 p->prev_pdu_file_offset = p->file_offset;
291         }
292
293         return num;
294 }
295
296
297 /****************************************************************************
298   wait device state on a pipe.  exactly what this is for is unknown...
299 ****************************************************************************/
300 BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority)
301 {
302         if (p == NULL) return False;
303
304         if (p->open)
305         {
306                 DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n",
307                          timestring(), priority, p->name));
308
309                 p->priority = priority;
310                 
311                 return True;
312         } 
313
314         DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n",
315                  timestring(), priority, p->name));
316         return False;
317 }
318
319
320 /****************************************************************************
321   set device state on a pipe.  exactly what this is for is unknown...
322 ****************************************************************************/
323 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
324 {
325         if (p == NULL) return False;
326
327         if (p->open) {
328                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
329                          timestring(), device_state, p->name));
330
331                 p->device_state = device_state;
332                 
333                 return True;
334         } 
335
336         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
337                  timestring(), device_state, p->name));
338         return False;
339 }
340
341
342 /****************************************************************************
343   close an rpc pipe
344 ****************************************************************************/
345 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
346 {
347         if (!p) {
348                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
349                 return False;
350         }
351
352         mem_buf_free(&(p->rdata.data));
353         mem_buf_free(&(p->rhdr .data));
354
355         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
356
357         pipes_open--;
358
359         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
360                  p->name, p->pnum, pipes_open));  
361
362         DLIST_REMOVE(Pipes, p);
363
364         ZERO_STRUCTP(p);
365
366         free(p);
367         
368         return True;
369 }
370
371 /****************************************************************************
372   close an rpc pipe
373 ****************************************************************************/
374 pipes_struct *get_rpc_pipe_p(char *buf, int where)
375 {
376         int pnum = SVAL(buf,where);
377
378         if (chain_p) return chain_p;
379
380         return get_rpc_pipe(pnum);
381 }
382
383 /****************************************************************************
384   close an rpc pipe
385 ****************************************************************************/
386 pipes_struct *get_rpc_pipe(int pnum)
387 {
388         pipes_struct *p;
389
390         DEBUG(4,("search for pipe pnum=%x\n", pnum));
391
392         for (p=Pipes;p;p=p->next)
393         {
394                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
395                           p->name, p->pnum, pipes_open));  
396         }
397
398         for (p=Pipes;p;p=p->next)
399         {
400                 if (p->pnum == pnum)
401                 {
402                         chain_p = p;
403                         return p;
404                 }
405         }
406
407         return NULL;
408 }
409