diff options
Diffstat (limited to 'source3/rpc_server/srv_pipe_hnd.c')
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c new file mode 100644 index 0000000000..e4893fee89 --- /dev/null +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -0,0 +1,315 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" + + +#define PIPE "\\PIPE\\" +#define PIPELEN strlen(PIPE) + +extern int DEBUGLEVEL; +static int chain_pnum = -1; + +#ifndef MAX_OPEN_PIPES +#define MAX_OPEN_PIPES 50 +#endif + +#define PIPE_HANDLE_OFFSET 0x800 + +pipes_struct Pipes[MAX_OPEN_PIPES]; + +#define P_OPEN(p) ((p)->open) +#define P_OK(p,c) (P_OPEN(p) && (c)==((p)->cnum)) +#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) +#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && P_OPEN(&(Pipes[pnum]))) +#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum) + + +/**************************************************************************** + reset pipe chain handle number +****************************************************************************/ +void reset_chain_pnum(void) +{ + chain_pnum = -1; +} + +/**************************************************************************** + sets chain pipe-file handle +****************************************************************************/ +void set_chain_pnum(int new_pnum) +{ + chain_pnum = new_pnum; +} + +/**************************************************************************** + initialise pipe handle states... +****************************************************************************/ +void init_rpc_pipe_hnd(void) +{ + int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ + for (i = 1; i < MAX_OPEN_PIPES; i++) + { + Pipes[i].open = False; + Pipes[i].name[0] = 0; + Pipes[i].pipe_srv_name[0] = 0; + + Pipes[i].rhdr.data = NULL; + Pipes[i].rdata.data = NULL; + Pipes[i].rhdr.offset = 0; + Pipes[i].rdata.offset = 0; + + Pipes[i].max_rdata_len = 0; + Pipes[i].hdr_offsets = 0; + } + + return; +} + +/**************************************************************************** + find first available file slot +****************************************************************************/ +int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid) +{ + int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ + for (i = 1; i < MAX_OPEN_PIPES; i++) + { + if (!Pipes[i].open) + { + Pipes[i].open = True; + Pipes[i].device_state = 0; + Pipes[i].cnum = cnum; + Pipes[i].uid = vuid; + + Pipes[i].rhdr.data = NULL; + Pipes[i].rdata.data = NULL; + Pipes[i].rhdr.offset = 0; + Pipes[i].rdata.offset = 0; + + Pipes[i].max_rdata_len = 0; + Pipes[i].hdr_offsets = 0; + + fstrcpy(Pipes[i].name, pipe_name); + + DEBUG(4,("Opened pipe %s with handle %x\n", + pipe_name, i + PIPE_HANDLE_OFFSET)); + + set_chain_pnum(i); + + return(i); + } + } + + DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n")); + + return(-1); +} + +/**************************************************************************** + reads data from a pipe. + + headers are interspersed with the data at regular intervals. by the time + this function is called, the start of the data could possibly have been + read by an SMBtrans (max_rdata_len != 0). + + calling create_rpc_request() here is a fudge. the data should already + have been prepared into arrays of headers + data stream sections. + + ****************************************************************************/ +int read_pipe(uint16 pnum, char *data, uint32 pos, int n) +{ + int data_pos = pos; + pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET]; + DEBUG(6,("read_pipe: %x", pnum)); + + if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("name: %s cnum: %d open: %s data_pos: %lx len: %lx", + p->name, + p->cnum, + BOOLSTR(p->open), + data_pos, n)); + } + + if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + int num; + int len; + uint32 rpc_frag_pos; + + DEBUG(6,("OK\n")); + + if (p->rhdr.data == NULL || p->rhdr.data->data == NULL || + p->rhdr.data->data_used == 0) + { + return 0; + } + + /* the read request starts from where the SMBtrans2 left off. */ + data_pos += p->max_rdata_len; + + /* headers accumulate an offset */ + data_pos -= p->hdr_offsets; + + len = mem_buf_len(p->rhdr.data); + num = len - (int)data_pos; + + if (num > n) num = n; + + if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST)) + { + rpc_frag_pos = data_pos % p->hdr.frag_len; + + if (rpc_frag_pos == 0) + { + /* create and copy in a new header. */ + create_rpc_reply(p, data_pos, p->rdata.offset); + mem_buf_copy(data, p->rhdr.data, 0, 0x18); + + /* make room in data stream for header */ + p->hdr_offsets += 0x18; + } + } + + if (num > 0) + { + mem_buf_copy(data, p->rhdr.data, data_pos, num); + return num; + } + + return 0; + + } + else + { + DEBUG(6,("NOT\n")); + return -1; + } +} + +/**************************************************************************** + gets the name of a pipe +****************************************************************************/ +BOOL get_rpc_pipe(int pnum, pipes_struct **p) +{ + DEBUG(6,("get_rpc_pipe: ")); + + /* mapping is PIPE_HANDLE_OFFSET up... */ + + if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("name: %s cnum: %d open: %s ", + Pipes[pnum - PIPE_HANDLE_OFFSET].name, + Pipes[pnum - PIPE_HANDLE_OFFSET].cnum, + BOOLSTR(Pipes[pnum - PIPE_HANDLE_OFFSET].open))); + } + if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("OK\n")); + (*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]); + return True; + } + else + { + DEBUG(6,("NOT\n")); + return False; + } +} + +/**************************************************************************** + gets the name of a pipe +****************************************************************************/ +char *get_rpc_pipe_hnd_name(int pnum) +{ + pipes_struct *p = NULL; + get_rpc_pipe(pnum, &p); + return p != NULL ? p->name : NULL; +} + +/**************************************************************************** + set device state on a pipe. exactly what this is for is unknown... +****************************************************************************/ +BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state) +{ + if (p == NULL) return False; + + if (P_OPEN(p)) + { + DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n", + timestring(), device_state, p->name, p->cnum)); + + p->device_state = device_state; + + return True; + } + else + { + DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n", + timestring(), device_state, p->name, p->cnum)); + return False; + } +} + +/**************************************************************************** + close an rpc pipe +****************************************************************************/ +BOOL close_rpc_pipe_hnd(int pnum, int cnum) +{ + pipes_struct *p = NULL; + get_rpc_pipe(pnum, &p); + /* mapping is PIPE_HANDLE_OFFSET up... */ + + if (p != NULL && P_OK(p, cnum)) + { + DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n", + timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum)); + + p->open = False; + + p->rdata.offset = 0; + p->rhdr.offset = 0; + mem_buf_free(&(p->rdata.data)); + mem_buf_free(&(p->rhdr .data)); + + return True; + } + else + { + DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n", + timestring(),pnum, cnum)); + return False; + } +} + +/**************************************************************************** + close an rpc pipe +****************************************************************************/ +int get_rpc_pipe_num(char *buf, int where) +{ + return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where)); +} + |