4d5fd3865e3251834dbf1ac5d7f976e79a11a963
[tprouty/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-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
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->conn = conn;
127         p->vuid  = vuid;
128         
129         p->rhdr.data  = NULL;
130         p->rdata.data = NULL;
131         p->rhdr.offset  = 0;
132         p->rdata.offset = 0;
133         
134         p->file_offset     = 0;
135         p->hdr_offsets     = 0;
136         p->frag_len_left   = 0;
137         p->next_frag_start = 0;
138         
139         fstrcpy(p->name, pipe_name);
140         
141         DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
142                  pipe_name, i, pipes_open));
143         
144         chain_p = p;
145         
146         /* OVERWRITE p as a temp variable, to display all open pipes */ 
147         for (p = Pipes; p; p = p->next)
148         {
149                 DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  
150         }
151
152         return chain_p;
153 }
154
155
156 /****************************************************************************
157  writes data to a pipe.
158
159  SERIOUSLY ALPHA CODE!
160  ****************************************************************************/
161 int write_pipe(pipes_struct *p, char *data, int n)
162 {
163         prs_struct pd;
164         struct mem_buf data_buf;
165
166         DEBUG(6,("write_pipe: %x", p->pnum));
167
168         DEBUG(6,("name: %s open: %s len: %d",
169                  p->name, BOOLSTR(p->open), n));
170
171         dump_data(50, data, n);
172
173         /* fake up a data buffer from the write_pipe data parameters */
174         mem_create(&data_buf, data, n, 0, False);
175         data_buf.offset.start = 0;
176         data_buf.offset.end   = n;
177
178         /* fake up a parsing structure */
179         pd.data = &data_buf;
180         pd.align = 4;
181         pd.io = True;
182         pd.offset = 0;
183
184         return rpc_command(p, &pd) ? n : -1;
185 }
186
187
188 /****************************************************************************
189  reads data from a pipe.
190
191  headers are interspersed with the data at regular intervals.  by the time
192  this function is called, the start of the data could possibly have been
193  read by an SMBtrans (file_offset != 0).
194
195  calling create_rpc_request() here is a fudge.  the data should already
196  have been prepared into arrays of headers + data stream sections.
197
198  ****************************************************************************/
199 int read_pipe(pipes_struct *p, char *data, uint32 pos, int n)
200 {
201         int num = 0;
202         int len = 0;
203         uint32 hdr_num = 0;
204         int data_hdr_pos;
205         int data_pos;
206
207         DEBUG(6,("read_pipe: %x", p->pnum));
208
209         DEBUG(6,("name: %s open: %s pos: %d len: %d",
210                  p->name,
211                  BOOLSTR(p->open),
212                  pos, n));
213
214         if (!p || !p->open)
215         {
216                 DEBUG(6,("pipe not open\n"));
217                 return -1;              
218         }
219
220
221         if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
222             p->rhdr.data->data_used == 0)
223         {
224                 return 0;
225         }
226
227         DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
228                  p, p->file_offset, n));
229         DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n",
230                  p->frag_len_left, p->next_frag_start));
231
232         /* the read request starts from where the SMBtrans2 left off. */
233         data_pos     = p->file_offset - p->hdr_offsets;
234         data_hdr_pos = p->file_offset;
235
236         len = mem_buf_len(p->rhdr.data);
237         num = len - (int)data_pos;
238         
239         DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n));
240         
241         if (num > n) num = n;
242         if (num <= 0)
243         {
244                 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
245                 return 0;
246         }
247
248         if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
249         {
250                 /* intermediate fragment - possibility of another header */
251                 
252                 DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n",
253                          p->hdr.frag_len, data_pos, data_hdr_pos));
254                 
255                 if (data_hdr_pos == p->next_frag_start)
256                 {
257                         DEBUG(6,("read_pipe: next fragment header\n"));
258
259                         /* this is subtracted from the total data bytes, later */
260                         hdr_num = 0x18;
261
262                         /* create and copy in a new header. */
263                         create_rpc_reply(p, data_pos, p->rdata.offset);
264                         mem_buf_copy(data, p->rhdr.data, 0, 0x18);
265                         
266                         data += 0x18;
267                         p->frag_len_left = p->hdr.frag_len;
268                         p->next_frag_start += p->hdr.frag_len;
269                         p->hdr_offsets += 0x18;
270                 }                       
271         }
272         
273         if (num < hdr_num)
274         {
275                 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
276         }
277
278         DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n",
279                  data_pos, num - hdr_num));
280         mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num);
281         
282         data_pos += num;
283         data_hdr_pos += num;
284         
285         if (hdr_num == 0x18 && num == 0x18)
286         {
287                 DEBUG(6,("read_pipe: just header read\n"));
288
289                 /* advance to the next fragment */
290                 p->frag_len_left -= 0x18; 
291         }
292         else if (data_hdr_pos == p->next_frag_start)
293         {
294                 DEBUG(6,("read_pipe: next fragment expected\n"));
295         }
296
297         p->file_offset  += num;
298         
299         return num;
300 }
301
302
303 /****************************************************************************
304   set device state on a pipe.  exactly what this is for is unknown...
305 ****************************************************************************/
306 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
307 {
308         if (p == NULL) return False;
309
310         if (p->open) {
311                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n",
312                          timestring(), device_state, p->name));
313
314                 p->device_state = device_state;
315                 
316                 return True;
317         } 
318
319         DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n",
320                  timestring(), device_state, p->name));
321         return False;
322 }
323
324
325 /****************************************************************************
326   close an rpc pipe
327 ****************************************************************************/
328 BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
329 {
330         if (!p) {
331                 DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
332                 return False;
333         }
334
335         mem_buf_free(&(p->rdata.data));
336         mem_buf_free(&(p->rhdr .data));
337
338         bitmap_clear(bmap, p->pnum - pipe_handle_offset);
339
340         pipes_open--;
341
342         DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", 
343                  p->name, p->pnum, pipes_open));  
344
345         DLIST_REMOVE(Pipes, p);
346
347         ZERO_STRUCTP(p);
348
349         free(p);
350         
351         return True;
352 }
353
354 /****************************************************************************
355   close an rpc pipe
356 ****************************************************************************/
357 pipes_struct *get_rpc_pipe_p(char *buf, int where)
358 {
359         int pnum = SVAL(buf,where);
360
361         if (chain_p) return chain_p;
362
363         return get_rpc_pipe(pnum);
364 }
365
366 /****************************************************************************
367   close an rpc pipe
368 ****************************************************************************/
369 pipes_struct *get_rpc_pipe(int pnum)
370 {
371         pipes_struct *p;
372
373         DEBUG(4,("search for pipe pnum=%x\n", pnum));
374
375         for (p=Pipes;p;p=p->next)
376         {
377                 DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
378                           p->name, p->pnum, pipes_open));  
379         }
380
381         for (p=Pipes;p;p=p->next)
382         {
383                 if (p->pnum == pnum)
384                 {
385                         chain_p = p;
386                         return p;
387                 }
388         }
389
390         return NULL;
391 }
392