"For I have laboured mightily on Luke's code, and hath broken
[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 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].max_rdata_len = 0;
85                 Pipes[i].hdr_offsets   = 0;
86         }
87
88         return;
89 }
90
91 /****************************************************************************
92   find first available file slot
93 ****************************************************************************/
94 int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid)
95 {
96         int i;
97         /* we start at 1 here for an obscure reason I can't now remember,
98         but I think is important :-) */
99         for (i = 1; i < MAX_OPEN_PIPES; i++)
100         {
101                 if (!Pipes[i].open)
102                 {
103                         Pipes[i].open = True;
104                         Pipes[i].device_state = 0;
105                         Pipes[i].cnum = cnum;
106                         Pipes[i].uid  = vuid;
107
108                         Pipes[i].rhdr.data  = NULL;
109                         Pipes[i].rdata.data = NULL;
110                         Pipes[i].rhdr.offset  = 0;
111                         Pipes[i].rdata.offset = 0;
112
113                         Pipes[i].max_rdata_len = 0;
114                         Pipes[i].hdr_offsets   = 0;
115
116                         fstrcpy(Pipes[i].name, pipe_name);
117
118                         DEBUG(4,("Opened pipe %s with handle %x\n",
119                                    pipe_name, i + PIPE_HANDLE_OFFSET));
120
121                         set_chain_pnum(i);
122
123                         return(i);
124                 }
125         }
126
127         DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n"));
128
129         return(-1);
130 }
131
132 /****************************************************************************
133  reads data from a pipe.
134
135  headers are interspersed with the data at regular intervals.  by the time
136  this function is called, the start of the data could possibly have been
137  read by an SMBtrans (max_rdata_len != 0).
138
139  calling create_rpc_request() here is a fudge.  the data should already
140  have been prepared into arrays of headers + data stream sections.
141
142  ****************************************************************************/
143 int read_pipe(uint16 pnum, char *data, uint32 pos, int n)
144 {
145         int data_pos = pos;
146         pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET];
147         DEBUG(6,("read_pipe: %x", pnum));
148
149         if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
150         {
151                 DEBUG(6,("name: %s cnum: %d open: %s data_pos: %lx len: %lx",
152                           p->name,
153                           p->cnum,
154                           BOOLSTR(p->open),
155                           data_pos, n));
156         }
157
158         if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
159         {
160                 int num;
161                 int len;
162                 uint32 rpc_frag_pos;
163
164                 DEBUG(6,("OK\n"));
165
166                 if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
167                     p->rhdr.data->data_used == 0)
168                 {
169                         return 0;
170                 }
171
172                 /* the read request starts from where the SMBtrans2 left off. */
173                 data_pos += p->max_rdata_len;
174
175                 /* headers accumulate an offset */
176                 data_pos -= p->hdr_offsets;
177
178                 len = mem_buf_len(p->rhdr.data);
179                 num = len - (int)data_pos;
180
181                 if (num > n) num = n;
182
183                 if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
184                 {
185                         rpc_frag_pos = data_pos % p->hdr.frag_len;
186
187                         if (rpc_frag_pos == 0)
188                         {
189                                 /* create and copy in a new header. */
190                                 create_rpc_reply(p, data_pos, p->rdata.offset);
191                                 mem_buf_copy(data, p->rhdr.data, 0, 0x18);
192
193                                 /* make room in data stream for header */
194                                 p->hdr_offsets += 0x18;
195                         }
196                 }
197
198                 if (num > 0)
199                 {
200                         mem_buf_copy(data, p->rhdr.data, data_pos, num);
201                         return num;
202                 }
203
204                 return 0;
205
206         }
207         else
208         {
209                 DEBUG(6,("NOT\n"));
210                 return -1;
211         }
212 }
213
214 /****************************************************************************
215   gets the name of a pipe
216 ****************************************************************************/
217 BOOL get_rpc_pipe(int pnum, pipes_struct **p)
218 {
219         DEBUG(6,("get_rpc_pipe: "));
220
221         /* mapping is PIPE_HANDLE_OFFSET up... */
222
223         if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
224         {
225                 DEBUG(6,("name: %s cnum: %d open: %s ",
226                           Pipes[pnum - PIPE_HANDLE_OFFSET].name,
227                           Pipes[pnum - PIPE_HANDLE_OFFSET].cnum,
228                           BOOLSTR(Pipes[pnum - PIPE_HANDLE_OFFSET].open)));
229         }
230         if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
231         {
232                 DEBUG(6,("OK\n"));
233                 (*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]);
234                 return True;
235         }
236         else
237         {
238                 DEBUG(6,("NOT\n"));
239                 return False;
240         }
241 }
242
243 /****************************************************************************
244   gets the name of a pipe
245 ****************************************************************************/
246 char *get_rpc_pipe_hnd_name(int pnum)
247 {
248         pipes_struct *p = NULL;
249         get_rpc_pipe(pnum, &p);
250         return p != NULL ? p->name : NULL;
251 }
252
253 /****************************************************************************
254   set device state on a pipe.  exactly what this is for is unknown...
255 ****************************************************************************/
256 BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
257 {
258         if (p == NULL) return False;
259
260         if (P_OPEN(p))
261         {
262                 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n",
263                          timestring(), device_state, p->name, p->cnum));
264
265                 p->device_state = device_state;
266    
267                 return True;
268         }
269         else
270         {
271                 DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n",
272                           timestring(), device_state, p->name, p->cnum));
273                 return False;
274         }
275 }
276
277 /****************************************************************************
278   close an rpc pipe
279 ****************************************************************************/
280 BOOL close_rpc_pipe_hnd(int pnum, int cnum)
281 {
282         pipes_struct *p = NULL;
283         get_rpc_pipe(pnum, &p);
284   /* mapping is PIPE_HANDLE_OFFSET up... */
285
286   if (p != NULL && P_OK(p, cnum))
287   {
288     DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n",
289            timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum));
290   
291     p->open = False;
292
293         p->rdata.offset = 0;
294         p->rhdr.offset = 0;
295         mem_buf_free(&(p->rdata.data));
296         mem_buf_free(&(p->rhdr .data));
297
298     return True;
299   }
300   else
301   {
302     DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n",
303            timestring(),pnum, cnum));
304     return False;
305   }
306 }
307
308 /****************************************************************************
309   close an rpc pipe
310 ****************************************************************************/
311 int get_rpc_pipe_num(char *buf, int where)
312 {
313         return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where));
314 }
315