summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ntdomain.h7
-rw-r--r--source3/include/proto.h2
-rw-r--r--source3/rpc_server/srv_lsa_hnd.c94
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c8
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c53
5 files changed, 120 insertions, 44 deletions
diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h
index 799fa6d907..f56b765d29 100644
--- a/source3/include/ntdomain.h
+++ b/source3/include/ntdomain.h
@@ -153,8 +153,9 @@ struct policy
};
struct handle_list {
- struct policy *Policy;
- size_t count;
+ struct policy *Policy; /* List of policies. */
+ size_t count; /* Current number of handles. */
+ size_t pipe_ref_count; /* Number of pipe handles referring to this list. */
};
/* Domain controller authentication protocol info */
@@ -246,7 +247,7 @@ typedef struct pipes_struct
TALLOC_CTX *mem_ctx;
/* handle database to use on this pipe. */
- struct handle_list pipe_handles;
+ struct handle_list *pipe_handles;
} pipes_struct;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 006b26cf05..331d080f54 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3454,7 +3454,7 @@ BOOL api_ntlsa_rpc(pipes_struct *p);
/*The following definitions come from rpc_server/srv_lsa_hnd.c */
-void init_pipe_handles(pipes_struct *p);
+BOOL init_pipe_handle_list(pipes_struct *p, char *pipe_name);
BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *), void *data_ptr);
BOOL find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p);
BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd);
diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c
index bcc3878d86..d0a26abc6b 100644
--- a/source3/rpc_server/srv_lsa_hnd.c
+++ b/source3/rpc_server/srv_lsa_hnd.c
@@ -25,19 +25,63 @@
extern int DEBUGLEVEL;
-/* This is the max handles per pipe. */
+/* This is the max handles across all instances of a pipe name. */
#ifndef MAX_OPEN_POLS
-#define MAX_OPEN_POLS 256
+#define MAX_OPEN_POLS 1024
#endif
/****************************************************************************
- initialise policy handle states...
+ Initialise a policy handle list on a pipe. Handle list is shared between all
+ pipes of the same name.
****************************************************************************/
-void init_pipe_handles(pipes_struct *p)
+BOOL init_pipe_handle_list(pipes_struct *p, char *pipe_name)
{
- p->pipe_handles.Policy = NULL;
- p->pipe_handles.count = 0;
+ pipes_struct *plist = get_first_pipe();
+ struct handle_list *hl = NULL;
+
+ for (plist = get_first_pipe(); plist; plist = get_next_pipe(plist)) {
+ if (strequal( plist->name, pipe_name)) {
+ if (!plist->pipe_handles) {
+ pstring msg;
+ slprintf(msg, sizeof(msg)-1, "init_pipe_handles: NULL pipe_handle pointer in pipe %s",
+ pipe_name );
+ smb_panic(msg);
+ }
+ hl = plist->pipe_handles;
+ break;
+ }
+ }
+
+ if (!hl) {
+ /*
+ * No handle list for this pipe (first open of pipe).
+ * Create list.
+ */
+
+ if ((hl = (struct handle_list *)malloc(sizeof(struct handle_list))) == NULL)
+ return False;
+ ZERO_STRUCTP(hl);
+
+ DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name ));
+ }
+
+ /*
+ * One more pipe is using this list.
+ */
+
+ hl->pipe_ref_count++;
+
+ /*
+ * Point this pipe at this list.
+ */
+
+ p->pipe_handles = hl;
+
+ DEBUG(10,("init_pipe_handles: pipe_handles ref count = %u for pipe %s\n",
+ p->pipe_handles->pipe_ref_count, pipe_name ));
+
+ return True;
}
/****************************************************************************
@@ -51,8 +95,9 @@ BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
struct policy *pol;
- if (p->pipe_handles.count > MAX_OPEN_POLS) {
- DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n", (int)p->pipe_handles.count));
+ if (p->pipe_handles->count > MAX_OPEN_POLS) {
+ DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
+ (int)p->pipe_handles->count));
return False;
}
@@ -78,12 +123,12 @@ BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
SIVAL(pol->pol_hnd.data5, 0, time(NULL)); /* something random */
SIVAL(pol->pol_hnd.data5, 4, sys_getpid()); /* something more random */
- DLIST_ADD(p->pipe_handles.Policy, pol);
- p->pipe_handles.count++;
+ DLIST_ADD(p->pipe_handles->Policy, pol);
+ p->pipe_handles->count++;
*hnd = pol->pol_hnd;
- DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles.count));
+ DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
dump_data(4, (char *)hnd, sizeof(*hnd));
return True;
@@ -101,7 +146,7 @@ static struct policy *find_policy_by_hnd_internal(pipes_struct *p, POLICY_HND *h
if (data_p)
*data_p = NULL;
- for (i = 0, pol=p->pipe_handles.Policy;pol;pol=pol->next, i++) {
+ for (i = 0, pol=p->pipe_handles->Policy;pol;pol=pol->next, i++) {
if (memcmp(&pol->pol_hnd, hnd, sizeof(*hnd)) == 0) {
DEBUG(4,("Found policy hnd[%d] ", (int)i));
dump_data(4, (char *)hnd, sizeof(*hnd));
@@ -144,9 +189,9 @@ BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
if (pol->free_fn && pol->data_ptr)
(*pol->free_fn)(pol->data_ptr);
- pol->p->pipe_handles.count--;
+ pol->p->pipe_handles->count--;
- DLIST_REMOVE(pol->p->pipe_handles.Policy, pol);
+ DLIST_REMOVE(pol->p->pipe_handles->Policy, pol);
ZERO_STRUCTP(pol);
@@ -156,14 +201,25 @@ BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
}
/****************************************************************************
- Close all the pipe handles.
+ Close a pipe - free the handle list if it was the last pipe reference.
****************************************************************************/
void close_policy_by_pipe(pipes_struct *p)
{
- while (p->pipe_handles.Policy)
- close_policy_hnd(p, &p->pipe_handles.Policy->pol_hnd);
+ p->pipe_handles->pipe_ref_count--;
+
+ if (p->pipe_handles->pipe_ref_count == 0) {
+ /*
+ * Last pipe open on this list - free the list.
+ */
+ while (p->pipe_handles->Policy)
+ close_policy_hnd(p, &p->pipe_handles->Policy->pol_hnd);
- p->pipe_handles.Policy = NULL;
- p->pipe_handles.count = 0;
+ p->pipe_handles->Policy = NULL;
+ p->pipe_handles->count = 0;
+
+ free(p->pipe_handles);
+ p->pipe_handles = NULL;
+ DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name ));
+ }
}
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index ed1f9d36db..893bc8cb88 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -163,7 +163,13 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
return NULL;
}
- init_pipe_handles(p);
+ if (!init_pipe_handle_list(p, pipe_name)) {
+ DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
+ talloc_destroy(p->mem_ctx);
+ free(p);
+ return NULL;
+ }
+
DLIST_ADD(Pipes, p);
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 9fcf9930bf..804fe8a523 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -569,7 +569,7 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
return False;
}
- DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles.count ));
+ DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
return True;
}
@@ -634,6 +634,8 @@ void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
fstring printer;
uint32 status;
struct pipes_struct *p;
+ struct policy *pol;
+ struct handle_list *hl;
*printer = '\0';
fstrcpy(printer,buf);
@@ -645,32 +647,43 @@ void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
- /* We need to enumerate all our pipes and all printers on them. */
+ /*
+ * We need to enumerate all printers. The handle list is shared
+ * across pipes of the same name, so just find the first open
+ * spoolss pipe.
+ */
+
+ hl = NULL;
for ( p = get_first_pipe(); p; get_next_pipe(p)) {
- struct policy *pol;
+ if (strequal(p->name, "spoolss")) {
+ hl = p->pipe_handles;
+ break;
+ }
+ }
- if (!strequal(p->name, "spoolss"))
- continue;
+ if (!hl) {
+ DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
+ return;
+ }
- /* Iterate the printer list on this pipe. */
- for (pol = p->pipe_handles.Policy; pol; pol = pol->next ) {
- Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
+ /* Iterate the printer list on this pipe. */
+ for (pol = hl->Policy; pol; pol = pol->next ) {
+ Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
- if (!find_printer)
- continue;
+ if (!find_printer)
+ continue;
- /*
- * if the entry is the given printer or if it's a printerserver
- * we send the message
- */
+ /*
+ * if the entry is the given printer or if it's a printerserver
+ * we send the message
+ */
- if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
- if (strcmp(find_printer->dev.handlename, printer))
- continue;
+ if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
+ if (strcmp(find_printer->dev.handlename, printer))
+ continue;
- if (find_printer->notify.client_connected==True)
- cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
- }
+ if (find_printer->notify.client_connected==True)
+ cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
}
}