diff options
Diffstat (limited to 'source3/rpc_server/srv_pipe_hnd.c')
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 432 |
1 files changed, 210 insertions, 222 deletions
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index bd29578f0e..dfc4eeba5f 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -28,36 +28,34 @@ #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) +/* this must be larger than the sum of the open files and directories */ +#define PIPE_HANDLE_OFFSET 0x7000 + extern int DEBUGLEVEL; -static int chain_pnum = -1; +static pipes_struct *chain_p; +static int pipes_open; #ifndef MAX_OPEN_PIPES -#define MAX_OPEN_PIPES 50 +#define MAX_OPEN_PIPES 64 #endif -pipes_struct Pipes[MAX_OPEN_PIPES]; - -#define P_OPEN(p) ((p)->open) -#define P_OK(p,c) (P_OPEN(p) && (c)==((p)->conn)) -#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) - +static pipes_struct *Pipes; +static struct bitmap *bmap; /**************************************************************************** reset pipe chain handle number ****************************************************************************/ -void reset_chain_pnum(void) +void reset_chain_p(void) { - chain_pnum = -1; + chain_p = NULL; } /**************************************************************************** sets chain pipe-file handle ****************************************************************************/ -void set_chain_pnum(int new_pnum) +void set_chain_p(pipes_struct *new_p) { - chain_pnum = new_pnum; + chain_p = new_p; } /**************************************************************************** @@ -65,71 +63,85 @@ void set_chain_pnum(int new_pnum) ****************************************************************************/ 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].file_offset = 0; - Pipes[i].hdr_offsets = 0; - Pipes[i].frag_len_left = 0; - Pipes[i].next_frag_start = 0; + bmap = bitmap_allocate(MAX_OPEN_PIPES); + if (!bmap) { + exit_server("out of memory in init_rpc_pipe_hnd\n"); } - - return; } + /**************************************************************************** find first available file slot ****************************************************************************/ -int open_rpc_pipe_hnd(char *pipe_name, connection_struct *conn, uint16 vuid) +pipes_struct *open_rpc_pipe_p(char *pipe_name, + connection_struct *conn, 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) break; + pipes_struct *p; + static int next_pipe; + + /* not repeating pipe numbers makes it easier to track things in + log files and prevents client bugs where pipe numbers are reused + over connection restarts */ + if (next_pipe == 0) { + next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES; } - if (i == MAX_OPEN_PIPES) { - DEBUG(1,("ERROR! Out of pipe structures\n")); - return(-1); + i = bitmap_find(bmap, next_pipe); + + if (i == -1) { + DEBUG(0,("ERROR! Out of pipe structures\n")); + return NULL; + } + + next_pipe = (i+1) % MAX_OPEN_PIPES; + + p = (pipes_struct *)malloc(sizeof(*p)); + if (!p) return NULL; + + /* hook into the front of the list */ + if (!Pipes) { + Pipes = p; + } else { + Pipes->prev = p; + p->next = Pipes; + Pipes = p; } - Pipes[i].open = True; - Pipes[i].device_state = 0; - Pipes[i].conn = conn; - Pipes[i].uid = vuid; + bitmap_set(bmap, i); + i += PIPE_HANDLE_OFFSET; + + pipes_open++; + + memset(p, 0, sizeof(*p)); + p->pnum = i; + + p->open = True; + p->device_state = 0; + p->conn = conn; + p->uid = vuid; - Pipes[i].rhdr.data = NULL; - Pipes[i].rdata.data = NULL; - Pipes[i].rhdr.offset = 0; - Pipes[i].rdata.offset = 0; + p->rhdr.data = NULL; + p->rdata.data = NULL; + p->rhdr.offset = 0; + p->rdata.offset = 0; - Pipes[i].file_offset = 0; - Pipes[i].hdr_offsets = 0; - Pipes[i].frag_len_left = 0; - Pipes[i].next_frag_start = 0; + p->file_offset = 0; + p->hdr_offsets = 0; + p->frag_len_left = 0; + p->next_frag_start = 0; - fstrcpy(Pipes[i].name, pipe_name); + fstrcpy(p->name, pipe_name); - DEBUG(4,("Opened pipe %s with handle %x\n", - pipe_name, i + PIPE_HANDLE_OFFSET)); + DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", + pipe_name, i, pipes_open)); - set_chain_pnum(i); + set_chain_p(p); - return(i); + return p; } + /**************************************************************************** reads data from a pipe. @@ -141,157 +153,111 @@ int open_rpc_pipe_hnd(char *pipe_name, connection_struct *conn, uint16 vuid) have been prepared into arrays of headers + data stream sections. ****************************************************************************/ -int read_pipe(uint16 pnum, char *data, uint32 pos, int n) +int read_pipe(pipes_struct *p, char *data, uint32 pos, int n) { - 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 open: %s pos: %d len: %d", - p->name, - BOOLSTR(p->open), - pos, n)); + int num = 0; + int len = 0; + uint32 hdr_num = 0; + int data_hdr_pos; + int data_pos; + + DEBUG(6,("read_pipe: %x", p->pnum)); + + DEBUG(6,("name: %s open: %s pos: %d len: %d", + p->name, + BOOLSTR(p->open), + pos, n)); + + if (!p || !p->open) { + DEBUG(6,("pipe not open\n")); + return -1; } - if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET)) - { - int num = 0; - int len = 0; - uint32 hdr_num = 0; - int data_hdr_pos; - int data_pos; - - DEBUG(6,("OK\n")); - - if (p->rhdr.data == NULL || p->rhdr.data->data == NULL || - p->rhdr.data->data_used == 0) - { - return 0; - } - - DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n", - p, p->file_offset, n)); - DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n", - p->frag_len_left, p->next_frag_start)); - - /* the read request starts from where the SMBtrans2 left off. */ - data_pos = p->file_offset - p->hdr_offsets; - data_hdr_pos = p->file_offset; - - len = mem_buf_len(p->rhdr.data); - num = len - (int)data_pos; - - DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n)); - if (num > n) num = n; - if (num <= 0) - { - DEBUG(5,("read_pipe: 0 or -ve data length\n")); - return 0; - } - - if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST)) - { - /* intermediate fragment - possibility of another header */ - - DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n", - p->hdr.frag_len, data_pos, data_hdr_pos)); - - if (data_hdr_pos == p->next_frag_start) - { - DEBUG(6,("read_pipe: next fragment header\n")); - - /* this is subtracted from the total data bytes, later */ - hdr_num = 0x18; - - /* 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); - - data += 0x18; - p->frag_len_left = p->hdr.frag_len; - p->next_frag_start += p->hdr.frag_len; - p->hdr_offsets += 0x18; - - /*DEBUG(6,("read_pipe: hdr_offsets: %d\n", p->hdr_offsets));*/ - } - } - - if (num < hdr_num) - { - DEBUG(5,("read_pipe: warning - data read only part of a header\n")); - } - - DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n", - data_pos, num - hdr_num)); - mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num); - - data_pos += num; - data_hdr_pos += num; - - if (hdr_num == 0x18 && num == 0x18) - { - DEBUG(6,("read_pipe: just header read\n")); + if (p->rhdr.data == NULL || p->rhdr.data->data == NULL || + p->rhdr.data->data_used == 0) { + return 0; + } - /* advance to the next fragment */ - p->frag_len_left -= 0x18; - } - else if (data_hdr_pos == p->next_frag_start) - { - DEBUG(6,("read_pipe: next fragment expected\n")); - } + DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n", + p, p->file_offset, n)); + DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n", + p->frag_len_left, p->next_frag_start)); - p->file_offset += num; + /* the read request starts from where the SMBtrans2 left off. */ + data_pos = p->file_offset - p->hdr_offsets; + data_hdr_pos = p->file_offset; - return num; + len = mem_buf_len(p->rhdr.data); + num = len - (int)data_pos; + + DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n)); + + if (num > n) num = n; + if (num <= 0) { + DEBUG(5,("read_pipe: 0 or -ve data length\n")); + return 0; + } + if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST)) { + /* intermediate fragment - possibility of another header */ + + DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n", + p->hdr.frag_len, data_pos, data_hdr_pos)); + + if (data_hdr_pos == p->next_frag_start) { + DEBUG(6,("read_pipe: next fragment header\n")); + + /* this is subtracted from the total data bytes, later */ + hdr_num = 0x18; + + /* 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); + + data += 0x18; + p->frag_len_left = p->hdr.frag_len; + p->next_frag_start += p->hdr.frag_len; + p->hdr_offsets += 0x18; + } + } - else - { - DEBUG(6,("NOT\n")); - return -1; + + if (num < hdr_num) { + DEBUG(5,("read_pipe: warning - data read only part of a header\n")); } -} - -/**************************************************************************** - 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... */ + DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n", + data_pos, num - hdr_num)); + mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num); + + data_pos += num; + data_hdr_pos += num; + + if (hdr_num == 0x18 && num == 0x18) { + DEBUG(6,("read_pipe: just header read\n")); - if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) - { - DEBUG(6,("name: %s open: %s ", - Pipes[pnum - PIPE_HANDLE_OFFSET].name, - 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; + /* advance to the next fragment */ + p->frag_len_left -= 0x18; + } else if (data_hdr_pos == p->next_frag_start) { + DEBUG(6,("read_pipe: next fragment expected\n")); } + + p->file_offset += num; + + return num; } + /**************************************************************************** gets the name of a pipe ****************************************************************************/ -char *get_rpc_pipe_hnd_name(int pnum) +char *get_rpc_pipe_hnd_name(pipes_struct *p) { - pipes_struct *p = NULL; - get_rpc_pipe(pnum, &p); - return p != NULL ? p->name : NULL; + return p?p->name:NULL; } + /**************************************************************************** set device state on a pipe. exactly what this is for is unknown... ****************************************************************************/ @@ -299,57 +265,79 @@ BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state) { if (p == NULL) return False; - if (P_OPEN(p)) - { + if (p->open) { DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n", timestring(), device_state, p->name)); p->device_state = device_state; - + return True; - } - else - { - DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n", - timestring(), device_state, p->name)); - return False; - } + } + + DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n", + timestring(), device_state, p->name)); + return False; } + /**************************************************************************** close an rpc pipe ****************************************************************************/ -BOOL close_rpc_pipe_hnd(int pnum, connection_struct *conn) +BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) { - pipes_struct *p = NULL; - get_rpc_pipe(pnum, &p); - /* mapping is PIPE_HANDLE_OFFSET up... */ - - if (p != NULL && P_OK(p, conn)) { - DEBUG(3,("%s Closed pipe name %s pnum=%x\n", - timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, - pnum)); - - 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\n", - timestring(),pnum)); + if (!p) { + DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n")); return False; } + + mem_buf_free(&(p->rdata.data)); + mem_buf_free(&(p->rhdr .data)); + + bitmap_clear(bmap, p->pnum - PIPE_HANDLE_OFFSET); + + pipes_open--; + + DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n", + p->name, p->pnum, pipes_open)); + + if (p == Pipes) { + Pipes = p->next; + if (Pipes) Pipes->prev = NULL; + } else { + p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + } + + memset(p, 0, sizeof(*p)); + + free(p); + + return True; } /**************************************************************************** close an rpc pipe ****************************************************************************/ -int get_rpc_pipe_num(char *buf, int where) +pipes_struct *get_rpc_pipe_p(char *buf, int where) { - return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where)); + int pnum = SVAL(buf,where); + + if (chain_p) return chain_p; + + return get_rpc_pipe(pnum); +} + +/**************************************************************************** + close an rpc pipe +****************************************************************************/ +pipes_struct *get_rpc_pipe(int pnum) +{ + pipes_struct *p; + + for (p=Pipes;p;p=p->next) { + if (p->pnum == pnum) return p; + } + + return NULL; } |