3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1997,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
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.
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.
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.
28 #define PIPE "\\PIPE\\"
29 #define PIPELEN strlen(PIPE)
31 extern int DEBUGLEVEL;
32 static int chain_pnum = -1;
34 #ifndef MAX_OPEN_PIPES
35 #define MAX_OPEN_PIPES 50
38 #define PIPE_HANDLE_OFFSET 0x800
40 pipes_struct Pipes[MAX_OPEN_PIPES];
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)
49 /****************************************************************************
50 reset pipe chain handle number
51 ****************************************************************************/
52 void reset_chain_pnum(void)
57 /****************************************************************************
58 sets chain pipe-file handle
59 ****************************************************************************/
60 void set_chain_pnum(int new_pnum)
62 chain_pnum = new_pnum;
65 /****************************************************************************
66 initialise pipe handle states...
67 ****************************************************************************/
68 void init_rpc_pipe_hnd(void)
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++)
75 Pipes[i].open = False;
77 Pipes[i].pipe_srv_name[0] = 0;
79 Pipes[i].rhdr.data = NULL;
80 Pipes[i].rdata.data = NULL;
81 Pipes[i].rhdr.offset = 0;
82 Pipes[i].rdata.offset = 0;
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;
93 /****************************************************************************
94 find first available file slot
95 ****************************************************************************/
96 int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid)
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++)
105 Pipes[i].open = True;
106 Pipes[i].device_state = 0;
107 Pipes[i].cnum = cnum;
110 Pipes[i].rhdr.data = NULL;
111 Pipes[i].rdata.data = NULL;
112 Pipes[i].rhdr.offset = 0;
113 Pipes[i].rdata.offset = 0;
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;
120 fstrcpy(Pipes[i].name, pipe_name);
122 DEBUG(4,("Opened pipe %s with handle %x\n",
123 pipe_name, i + PIPE_HANDLE_OFFSET));
131 DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n"));
136 /****************************************************************************
137 reads data from a pipe.
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).
143 calling create_rpc_request() here is a fudge. the data should already
144 have been prepared into arrays of headers + data stream sections.
146 ****************************************************************************/
147 int read_pipe(uint16 pnum, char *data, uint32 pos, int n)
151 pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET];
152 DEBUG(6,("read_pipe: %x", pnum));
154 if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
156 DEBUG(6,("name: %s cnum: %d open: %s data_pos: %d len: %d",
163 if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
171 if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
172 p->rhdr.data->data_used == 0)
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));
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;
186 len = mem_buf_len(p->rhdr.data);
187 num = len - (int)data_pos;
189 DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n));
191 if (num > n) num = n;
194 DEBUG(5,("read_pipe: 0 or -ve data length\n"));
198 if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
200 /* intermediate fragment - possibility of another header */
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));
205 if (data_hdr_pos == p->next_frag_start)
207 DEBUG(6,("read_pipe: next fragment header\n"));
209 /* this is subtracted from the total data bytes, later */
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);
217 p->frag_len_left = p->hdr.frag_len;
218 p->next_frag_start += p->hdr.frag_len;
219 p->hdr_offsets += 0x18;
221 /*DEBUG(6,("read_pipe: hdr_offsets: %d\n", p->hdr_offsets));*/
227 DEBUG(5,("read_pipe: warning - data read only part of a header\n"));
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);
237 if (hdr_num == 0x18 && num == 0x18)
239 DEBUG(6,("read_pipe: just header read\n"));
241 /* advance to the next fragment */
242 p->frag_len_left -= 0x18;
244 else if (data_hdr_pos == p->next_frag_start)
246 DEBUG(6,("read_pipe: next fragment expected\n"));
249 p->file_offset += num;
261 /****************************************************************************
262 gets the name of a pipe
263 ****************************************************************************/
264 BOOL get_rpc_pipe(int pnum, pipes_struct **p)
266 DEBUG(6,("get_rpc_pipe: "));
268 /* mapping is PIPE_HANDLE_OFFSET up... */
270 if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
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)));
277 if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
280 (*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]);
290 /****************************************************************************
291 gets the name of a pipe
292 ****************************************************************************/
293 char *get_rpc_pipe_hnd_name(int pnum)
295 pipes_struct *p = NULL;
296 get_rpc_pipe(pnum, &p);
297 return p != NULL ? p->name : NULL;
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)
305 if (p == NULL) return False;
309 DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n",
310 timestring(), device_state, p->name, p->cnum));
312 p->device_state = device_state;
318 DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n",
319 timestring(), device_state, p->name, p->cnum));
324 /****************************************************************************
326 ****************************************************************************/
327 BOOL close_rpc_pipe_hnd(int pnum, int cnum)
329 pipes_struct *p = NULL;
330 get_rpc_pipe(pnum, &p);
331 /* mapping is PIPE_HANDLE_OFFSET up... */
333 if (p != NULL && P_OK(p, cnum))
335 DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n",
336 timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum));
342 mem_buf_free(&(p->rdata.data));
343 mem_buf_free(&(p->rhdr .data));
349 DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n",
350 timestring(),pnum, cnum));
355 /****************************************************************************
357 ****************************************************************************/
358 int get_rpc_pipe_num(char *buf, int where)
360 return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where));