ABOUT time. dce/rpc long packet format now works, server-side.
[kai/samba.git] / source3 / 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 int chain_pnum = -1;
33
34 #ifndef MAX_OPEN_PIPES
35 #define MAX_OPEN_PIPES 50
36 #endif
37
38 #define PIPE_HANDLE_OFFSET 0x800
39
40 pipes_struct Pipes[MAX_OPEN_PIPES];
41
42 #define P_OPEN(p) ((p)->open)
43 #define P_OK(p,c) (P_OPEN(p) && (c)==((p)->cnum))
44 #define VALID_PNUM(pnum)   (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
45 #define OPEN_PNUM(pnum)    (VALID_PNUM(pnum) && P_OPEN(&(Pipes[pnum])))
46 #define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
47
48
49 /****************************************************************************
50   reset pipe chain handle number
51 ****************************************************************************/
52 void reset_chain_pnum(void)
53 {
54         chain_pnum = -1;
55 }
56
57 /****************************************************************************
58   sets chain pipe-file handle
59 ****************************************************************************/
60 void set_chain_pnum(int new_pnum)
61 {
62         chain_pnum = new_pnum;
63 }
64
65 /****************************************************************************
66   initialise pipe handle states...
67 ****************************************************************************/
68 void init_rpc_pipe_hnd(void)
69 {
70         int i;
71         /* we start at 1 here for an obscure reason I can't now remember,
72         but I think is important :-) */
73         for (i = 1; i < MAX_OPEN_PIPES; i++)
74         {
75                 Pipes[i].open = False;
76                 Pipes[i].name[0] = 0;
77                 Pipes[i].pipe_srv_name[0] = 0;
78
79                 Pipes[i].rhdr.data  = NULL;
80                 Pipes[i].rdata.data = NULL;
81                 Pipes[i].rhdr.offset  = 0;
82                 Pipes[i].rdata.offset = 0;
83
84                 Pipes[i].file_offset     = 0;
85                 Pipes[i].hdr_offsets     = 0;
86                 Pipes[i].frag_len_left   = 0;
87                 Pipes[i].next_frag_start = 0;
88         }
89
90         return;
91 }
92
93 /****************************************************************************
94   find first available file slot
95 ****************************************************************************/
96 int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid)
97 {
98         int i;
99         /* we start at 1 here for an obscure reason I can't now remember,
100         but I think is important :-) */
101         for (i = 1; i < MAX_OPEN_PIPES; i++)
102         {
103                 if (!Pipes[i].open)
104                 {
105                         Pipes[i].open = True;
106                         Pipes[i].device_state = 0;
107                         Pipes[i].cnum = cnum;
108                         Pipes[i].uid  = vuid;
109
110                         Pipes[i].rhdr.data  = NULL;
111                         Pipes[i].rdata.data = NULL;
112                         Pipes[i].rhdr.offset  = 0;
113                         Pipes[i].rdata.offset = 0;
114
115                         Pipes[i].file_offset     = 0;
116                         Pipes[i].hdr_offsets     = 0;
117                         Pipes[i].frag_len_left   = 0;
118                         Pipes[i].next_frag_start = 0;
119
120                         fstrcpy(Pipes[i].name, pipe_name);
121
122                         DEBUG(4,("Opened pipe %s with handle %x\n",
123                                    pipe_name, i + PIPE_HANDLE_OFFSET));
124
125                         set_chain_pnum(i);
126
127                         return(i);
128                 }
129         }
130
131         DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n"));
132
133         return(-1);
134 }
135
136 /****************************************************************************
137  reads data from a pipe.
138
139  headers are interspersed with the data at regular intervals.  by the time
140  this function is called, the start of the data could possibly have been
141  read by an SMBtrans (file_offset != 0).
142
143  calling create_rpc_request() here is a fudge.  the data should already
144  have been prepared into arrays of headers + data stream sections.
145
146  ****************************************************************************/
147 int read_pipe(uint16 pnum, char *data, uint32 pos, int n)
148 {
149         int data_hdr_pos;
150         int data_pos;
151         pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET];
152         DEBUG(6,("read_pipe: %x", pnum));
153
154         if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
155         {
156                 DEBUG(6,("name: %s cnum: %d open: %s data_pos: %d len: %d",
157                           p->name,
158                           p->cnum,
159                           BOOLSTR(p->open),
160                           data_pos, n));
161         }
162
163         if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
164         {
165                 int num = 0;
166                 int len = 0;
167                 uint32 hdr_num = 0;
168
169                 DEBUG(6,("OK\n"));
170
171                 if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
172                     p->rhdr.data->data_used == 0)
173                 {
174                         return 0;
175                 }
176
177                 DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n",
178                           p, p->file_offset, n));
179                 DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n",
180                           p->frag_len_left, p->next_frag_start));
181
182                 /* the read request starts from where the SMBtrans2 left off. */
183                 data_pos     = p->file_offset - p->hdr_offsets;
184                 data_hdr_pos = p->file_offset;
185
186                 len = mem_buf_len(p->rhdr.data);
187                 num = len - (int)data_pos;
188
189                 DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n));
190
191                 if (num > n) num = n;
192                 if (num <= 0)
193                 {
194                         DEBUG(5,("read_pipe: 0 or -ve data length\n"));
195                         return 0;
196                 }
197
198                 if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
199                 {
200                         /* intermediate fragment - possibility of another header */
201
202                         DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n",
203                                   p->hdr.frag_len, data_pos, data_hdr_pos));
204
205                         if (data_hdr_pos == p->next_frag_start)
206                         {
207                                 DEBUG(6,("read_pipe: next fragment header\n"));
208
209                                 /* this is subtracted from the total data bytes, later */
210                                 hdr_num = 0x18;
211
212                                 /* create and copy in a new header. */
213                                 create_rpc_reply(p, data_pos, p->rdata.offset);
214                                 mem_buf_copy(data, p->rhdr.data, 0, 0x18);
215
216                                 data += 0x18;
217                                 p->frag_len_left = p->hdr.frag_len;
218                                 p->next_frag_start += p->hdr.frag_len;
219                                 p->hdr_offsets += 0x18;
220
221                                 /*DEBUG(6,("read_pipe: hdr_offsets: %d\n", p->hdr_offsets));*/
222                         }
223                 }
224
225                 if (num < hdr_num)
226                 {
227                         DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
228                 }
229
230                 DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n",
231                                   data_pos, num - hdr_num));
232                 mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num);
233
234                 data_pos += num;
235                 data_hdr_pos += num;
236
237                 if (hdr_num == 0x18 && num == 0x18)
238                 {
239                         DEBUG(6,("read_pipe: just header read\n"));
240
241                         /* advance to the next fragment */
242                         p->frag_len_left -= 0x18; 
243                 }
244                 else if (data_hdr_pos == p->next_frag_start)
245                 {
246                         DEBUG(6,("read_pipe: next fragment expected\n"));
247                 }
248
249                 p->file_offset  += num;
250
251                 return num;
252
253         }
254         else
255         {
256                 DEBUG(6,("NOT\n"));
257                 return -1;
258         }
259 }
260
261 /****************************************************************************
262   gets the name of a pipe
263 ****************************************************************************/
264 BOOL get_rpc_pipe(int pnum, pipes_struct **p)
265 {
266         DEBUG(6,("get_rpc_pipe: "));
267
268         /* mapping is PIPE_HANDLE_OFFSET up... */
269
270         if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
271         {
272                 DEBUG(6,("name: %s cnum: %d open: %s ",
273                           Pipes[pnum - PIPE_HANDLE_OFFSET].name,
274                           Pipes[pnum - PIPE_HANDLE_OFFSET].cnum,
275                           BOOLSTR(Pipes[pnum - PIPE_HANDLE_OFFSET].open)));
276         }
277         if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
278         {
279                 DEBUG(6,("OK\n"));
280                 (*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]);
281                 return True;
282         }
283         else
284         {
285                 DEBUG(6,("NOT\n"));
286                 return False;
287         }
288 }
289
290 /****************************************************************************
291   gets the name of a pipe
292 ****************************************************************************/
293 char *get_rpc_pipe_hnd_name(int pnum)
294 {
295         pipes_struct *p = NULL;
296         get_rpc_pipe(pnum, &p);
297         return p != NULL ? p->name : NULL;
298 }
299
300 /****************************************************************************
301   set device state on a pipe.  exactly what this is for is unknown...
302 ****************************************************************************/
303 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
304 {
305         if (p == NULL) return False;
306
307         if (P_OPEN(p))
308         {
309                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n",
310                          timestring(), device_state, p->name, p->cnum));
311
312                 p->device_state = device_state;
313    
314                 return True;
315         }
316         else
317         {
318                 DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n",
319                           timestring(), device_state, p->name, p->cnum));
320                 return False;
321         }
322 }
323
324 /****************************************************************************
325   close an rpc pipe
326 ****************************************************************************/
327 BOOL close_rpc_pipe_hnd(int pnum, int cnum)
328 {
329         pipes_struct *p = NULL;
330         get_rpc_pipe(pnum, &p);
331   /* mapping is PIPE_HANDLE_OFFSET up... */
332
333   if (p != NULL && P_OK(p, cnum))
334   {
335     DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n",
336            timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum));
337   
338     p->open = False;
339
340         p->rdata.offset = 0;
341         p->rhdr.offset = 0;
342         mem_buf_free(&(p->rdata.data));
343         mem_buf_free(&(p->rhdr .data));
344
345     return True;
346   }
347   else
348   {
349     DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n",
350            timestring(),pnum, cnum));
351     return False;
352   }
353 }
354
355 /****************************************************************************
356   close an rpc pipe
357 ****************************************************************************/
358 int get_rpc_pipe_num(char *buf, int where)
359 {
360         return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where));
361 }
362