[SCM] Samba Shared Repository - branch master updated

Andreas Schneider asn at samba.org
Fri Sep 10 08:12:14 MDT 2010


The branch, master has been updated
       via  fc1a5db s3-spoolss: Don't leak memory on the session counter list.
       via  ed2c06f s3-spoolss: Allow multiple client backchannels.
       via  a736385 s3-spoolss: Split function to send notification.
       via  9db2be2 s3-spoolss: Use a single structure for all the back channel data.
       via  433ac75 s3-spoolss: Rename Printer_entry to struct printer_handle.
       via  4a8d042 s3-spoolss: Move Printer_entry to srv_spoolss_nt.c
       via  e257e68 s3-spoolss: Allocate printer entries on the pipe struct.
       via  0e5b1a6 s3-spoolss: Rename session counter structure and use talloc.
      from  c59961d s3-dsgetdcname: cleanup receive_getdc_response a little.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit fc1a5dbffb1330bba0e4deebdf18b812ccc1a823
Author: Andreas Schneider <asn at samba.org>
Date:   Fri Sep 10 16:06:24 2010 +0200

    s3-spoolss: Don't leak memory on the session counter list.
    
    Thanks Günther, please check.

commit ed2c06f9da0401fb95dcc16b4d3a3bd4f27b09f2
Author: Simo Sorce <idra at samba.org>
Date:   Thu Jul 1 19:39:57 2010 -0400

    s3-spoolss: Allow multiple client backchannels.
    
    When we run spoolssd we need to support multiple clients connecting.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit a736385b9749fe127411348ff3e0d1cc4405e47f
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 18:35:29 2010 -0400

    s3-spoolss: Split function to send notification.
    
    More digestible this way.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit 9db2be245e89e14f4c95037f67e7092f298a74f5
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 14:19:43 2010 -0400

    s3-spoolss: Use a single structure for all the back channel data.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit 433ac757dcac5841a47db3350865771a5d7301b2
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 15:32:15 2010 -0400

    s3-spoolss: Rename Printer_entry to struct printer_handle.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit 4a8d042afa41510b557e13b2aafcff611a137f28
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 15:11:41 2010 -0400

    s3-spoolss: Move Printer_entry to srv_spoolss_nt.c
    
    It is used only there, and it is a good idea to make this one private and
    opaque to the rest of the code.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit e257e68b4bcd49c6401b0982e71f3f3085711750
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 12:19:41 2010 -0400

    s3-spoolss: Allocate printer entries on the pipe struct.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

commit 0e5b1a67d26f99ae6d6f5e05f968dd3107191791
Author: Simo Sorce <idra at samba.org>
Date:   Wed Jun 30 12:07:44 2010 -0400

    s3-spoolss: Rename session counter structure and use talloc.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/nt_printing.h       |   40 ---
 source3/include/proto.h             |    1 +
 source3/rpc_server/srv_spoolss_nt.c |  646 +++++++++++++++++++++--------------
 source3/smbd/server.c               |    9 +-
 4 files changed, 399 insertions(+), 297 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h
index f56ddcb..52b11fe 100644
--- a/source3/include/nt_printing.h
+++ b/source3/include/nt_printing.h
@@ -162,46 +162,6 @@ typedef struct {
 #define SPLHND_PORTMON_TCP	3
 #define SPLHND_PORTMON_LOCAL	4
 
-/* structure to store the printer handles */
-/* and a reference to what it's pointing to */
-/* and the notify info asked about */
-/* that's the central struct */
-typedef struct _Printer{
-	struct _Printer *prev, *next;
-	bool document_started;
-	bool page_started;
-	uint32 jobid; /* jobid in printing backend */
-	int printer_type;
-	fstring servername;
-	fstring sharename;
-	uint32 type;
-	uint32 access_granted;
-	struct {
-		uint32 flags;
-		uint32 options;
-		fstring localmachine;
-		uint32 printerlocal;
-		struct spoolss_NotifyOption *option;
-		struct policy_handle client_hnd;
-		bool client_connected;
-		uint32 change;
-		/* are we in a FindNextPrinterChangeNotify() call? */
-		bool fnpcn;
-		struct messaging_context *msg_ctx;
-	} notify;
-	struct {
-		fstring machine;
-		fstring user;
-	} client;
-
-	/* devmode sent in the OpenPrinter() call */
-	struct spoolss_DeviceMode *devmode;
-
-	/* TODO cache the printer info2 structure */
-	struct spoolss_PrinterInfo2 *info2;
-	
-} Printer_entry;
-
 /*
  * The printer attributes.
  * I #defined all of them (grabbed form MSDN)
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0b54932..5e2e0bf 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4386,6 +4386,7 @@ NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
 		      bool *is_data_outstanding);
 
 /* The following definitions come from rpc_server/srv_spoolss_nt.c  */
+void srv_spoolss_cleanup(void);
 
 void do_drv_upgrade_printer(struct messaging_context *msg,
 			    void *private_data,
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 8978971..b5e2ddb 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -57,21 +57,76 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-static Printer_entry *printers_list;
+#ifndef MAX_OPEN_PRINTER_EXS
+#define MAX_OPEN_PRINTER_EXS 50
+#endif
+
+struct notify_back_channel;
+
+/* structure to store the printer handles */
+/* and a reference to what it's pointing to */
+/* and the notify info asked about */
+/* that's the central struct */
+struct printer_handle {
+	struct printer_handle *prev, *next;
+	bool document_started;
+	bool page_started;
+	uint32 jobid; /* jobid in printing backend */
+	int printer_type;
+	fstring servername;
+	fstring sharename;
+	uint32 type;
+	uint32 access_granted;
+	struct {
+		uint32 flags;
+		uint32 options;
+		fstring localmachine;
+		uint32 printerlocal;
+		struct spoolss_NotifyOption *option;
+		struct policy_handle cli_hnd;
+		struct notify_back_channel *cli_chan;
+		uint32 change;
+		/* are we in a FindNextPrinterChangeNotify() call? */
+		bool fnpcn;
+		struct messaging_context *msg_ctx;
+	} notify;
+	struct {
+		fstring machine;
+		fstring user;
+	} client;
+
+	/* devmode sent in the OpenPrinter() call */
+	struct spoolss_DeviceMode *devmode;
 
-typedef struct _counter_printer_0 {
-	struct _counter_printer_0 *next;
-	struct _counter_printer_0 *prev;
+	/* TODO cache the printer info2 structure */
+	struct spoolss_PrinterInfo2 *info2;
+
+};
+
+static struct printer_handle *printers_list;
+
+struct printer_session_counter {
+	struct printer_session_counter *next;
+	struct printer_session_counter *prev;
 
 	int snum;
 	uint32_t counter;
-} counter_printer_0;
+};
 
-static counter_printer_0 *counter_list;
+static struct printer_session_counter *counter_list;
 
-static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
-static uint32_t smb_connections = 0;
+struct notify_back_channel {
+	struct notify_back_channel *prev, *next;
 
+	/* associated client */
+	struct sockaddr_storage client_address;
+
+	/* print notify back-channel pipe handle*/
+	struct rpc_pipe_client *cli_pipe;
+	uint32_t active_connections;
+};
+
+static struct notify_back_channel *back_channels;
 
 /* Map generic permissions to printer object specific permissions */
 
@@ -162,9 +217,8 @@ static int nt_printq_status(int v)
  Disconnect from the client
 ****************************************************************************/
 
-static void srv_spoolss_replycloseprinter(
-	int snum, struct policy_handle *handle,
-	struct messaging_context *msg_ctx)
+static void srv_spoolss_replycloseprinter(int snum,
+					  struct printer_handle *prn_hnd)
 {
 	WERROR result;
 	NTSTATUS status;
@@ -174,34 +228,40 @@ static void srv_spoolss_replycloseprinter(
 	 * by deregistering our PID.
 	 */
 
-	if (!print_notify_deregister_pid(snum))
-		DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
+	if (!print_notify_deregister_pid(snum)) {
+		DEBUG(0, ("Failed to register our pid for printer %s\n",
+			  lp_const_servicename(snum)));
+	}
 
 	/* weird if the test succeeds !!! */
-	if (smb_connections==0) {
-		DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
+	if (prn_hnd->notify.cli_chan == NULL ||
+	    prn_hnd->notify.cli_chan->active_connections == 0) {
+		DEBUG(0, ("Trying to close unexisting backchannel!\n"));
+		DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
+		TALLOC_FREE(prn_hnd->notify.cli_chan);
 		return;
 	}
 
-	status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
-						  handle,
-						  &result);
-	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
-		DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
-			win_errstr(result)));
+	status = rpccli_spoolss_ReplyClosePrinter(
+					prn_hnd->notify.cli_chan->cli_pipe,
+					talloc_tos(),
+					&prn_hnd->notify.cli_hnd,
+					&result);
+	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+		DEBUG(0, ("reply_close_printer failed [%s].\n",
+			  win_errstr(result)));
+	}
 
 	/* if it's the last connection, deconnect the IPC$ share */
-	if (smb_connections==1) {
+	if (prn_hnd->notify.cli_chan->active_connections == 1) {
 
-		cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
-		/*
-		 * The above call shuts down the pipe also.
-		 */
-		notify_cli_pipe = NULL;
+		cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
+		DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
+		TALLOC_FREE(prn_hnd->notify.cli_chan);
 
-		if (msg_ctx != NULL) {
-			messaging_deregister(msg_ctx, MSG_PRINTER_NOTIFY2,
-					     NULL);
+		if (prn_hnd->notify.msg_ctx != NULL) {
+			messaging_deregister(prn_hnd->notify.msg_ctx,
+					     MSG_PRINTER_NOTIFY2, NULL);
 
 			/*
 			 * Tell the serverid.tdb we're no longer
@@ -209,34 +269,39 @@ static void srv_spoolss_replycloseprinter(
 			 */
 
 			serverid_register_msg_flags(
-				messaging_server_id(msg_ctx),
+				messaging_server_id(prn_hnd->notify.msg_ctx),
 				false, FLAG_MSG_PRINT_NOTIFY);
 		}
 	}
 
-	smb_connections--;
+	if (prn_hnd->notify.cli_chan) {
+		prn_hnd->notify.cli_chan->active_connections--;
+	}
 }
 
 /****************************************************************************
  Functions to free a printer entry datastruct.
 ****************************************************************************/
 
-static int printer_entry_destructor(Printer_entry *Printer)
+static int printer_entry_destructor(struct printer_handle *Printer)
 {
-	if (Printer->notify.client_connected == true) {
+	if (Printer->notify.cli_chan != NULL &&
+	    Printer->notify.cli_chan->active_connections > 0) {
 		int snum = -1;
 
-		if ( Printer->printer_type == SPLHND_SERVER) {
-			snum = -1;
-			srv_spoolss_replycloseprinter(
-				snum, &Printer->notify.client_hnd,
-				Printer->notify.msg_ctx);
-		} else if (Printer->printer_type == SPLHND_PRINTER) {
+		switch(Printer->printer_type) {
+		case SPLHND_SERVER:
+			srv_spoolss_replycloseprinter(snum, Printer);
+			break;
+
+		case SPLHND_PRINTER:
 			snum = print_queue_snum(Printer->sharename);
-			if (snum != -1)
-				srv_spoolss_replycloseprinter(
-					snum, &Printer->notify.client_hnd,
-					Printer->notify.msg_ctx);
+			if (snum != -1) {
+				srv_spoolss_replycloseprinter(snum, Printer);
+			}
+			break;
+		default:
+			break;
 		}
 	}
 
@@ -245,8 +310,6 @@ static int printer_entry_destructor(Printer_entry *Printer)
 	Printer->notify.localmachine[0]='\0';
 	Printer->notify.printerlocal=0;
 	TALLOC_FREE(Printer->notify.option);
-	Printer->notify.client_connected = false;
-
 	TALLOC_FREE(Printer->devmode);
 
 	/* Remove from the internal list. */
@@ -258,10 +321,10 @@ static int printer_entry_destructor(Printer_entry *Printer)
   find printer index by handle
 ****************************************************************************/
 
-static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
-						struct policy_handle *hnd)
+static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
+							struct policy_handle *hnd)
 {
-	Printer_entry *find_printer = NULL;
+	struct printer_handle *find_printer = NULL;
 
 	if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
 		DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
@@ -277,7 +340,7 @@ static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
 
 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
 {
-	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+	struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
 
 	if (!Printer) {
 		DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
@@ -359,7 +422,7 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
 
 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
 {
-	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+	struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
 	WERROR result;
 
 	if (!Printer) {
@@ -409,7 +472,7 @@ static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle
 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
 			     int *number, struct share_params **params)
 {
-	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+	struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
 
 	if (!Printer) {
 		DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
@@ -434,7 +497,7 @@ static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
  Check if it's \\server or \\server\printer
 ****************************************************************************/
 
-static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
+static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
 {
 	DEBUG(3,("Setting printer type=%s\n", handlename));
 
@@ -473,7 +536,7 @@ static void prune_printername_cache(void)
 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 				 const struct auth_serversupplied_info *server_info,
 				 struct messaging_context *msg_ctx,
-				 Printer_entry *Printer,
+				 struct printer_handle *Printer,
 				 const char *handlename)
 {
 	int snum;
@@ -642,16 +705,17 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
 			     const char *name, uint32_t access_granted)
 {
-	Printer_entry *new_printer;
+	struct printer_handle *new_printer;
 
 	DEBUG(10,("open_printer_hnd: name [%s]\n", name));
 
-	new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
+	new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
 	if (new_printer == NULL) {
 		return false;
 	}
 	talloc_set_destructor(new_printer, printer_entry_destructor);
 
+	/* This also steals the printer_handle on the policy_handle */
 	if (!create_policy_hnd(p, hnd, new_printer)) {
 		TALLOC_FREE(new_printer);
 		return false;
@@ -694,7 +758,7 @@ static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
 	return true;
 }
 
-static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
+static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
 				uint16_t notify_field)
 {
 	struct spoolss_NotifyOption *option = p->notify.option;
@@ -1033,168 +1097,205 @@ static void construct_info_data(struct spoolss_Notify *info_data,
  back registered
  **********************************************************************/
 
-static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
+static int build_notify2_messages(TALLOC_CTX *mem_ctx,
+				  struct printer_handle *prn_hnd,
+				  SPOOLSS_NOTIFY_MSG *messages,
+				  uint32_t num_msgs,
+				  struct spoolss_Notify **_notifies,
+				  int *_count)
 {
-	Printer_entry 		 *p;
-	TALLOC_CTX		 *mem_ctx = notify_ctr_getctx( ctr );
-	SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
-	SPOOLSS_NOTIFY_MSG       *messages;
-	int			 sending_msg_count;
-
-	if ( !msg_group ) {
-		DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
-		return;
-	}
-
-	messages = msg_group->msgs;
+	struct spoolss_Notify *notifies;
+	SPOOLSS_NOTIFY_MSG *msg;
+	int count = 0;
+	uint32_t id;
+	int i;
 
-	if ( !messages ) {
-		DEBUG(5,("send_notify2_changes() called with no messages!\n"));
-		return;
+	notifies = talloc_zero_array(mem_ctx,
+				     struct spoolss_Notify, num_msgs);
+	if (!notifies) {
+		return ENOMEM;
 	}
 
-	DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
+	for (i = 0; i < num_msgs; i++) {
 
-	/* loop over all printers */
-
-	for (p = printers_list; p; p = p->next) {
-		struct spoolss_Notify *notifies;
-		uint32_t count = 0;
-		uint32_t id;
-		int 	i;
+		msg = &messages[i];
 
-		/* Is there notification on this handle? */
+		/* Are we monitoring this event? */
 
-		if ( !p->notify.client_connected )
+		if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
 			continue;
+		}
 
-		DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
+		DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
+			   "for printer [%s]\n",
+			   msg->type, msg->field, prn_hnd->sharename));
 
-		/* For this printer?  Print servers always receive
-                   notifications. */
+		/*
+		 * if the is a printer notification handle and not a job
+		 * notification type, then set the id to 0.
+		 * Otherwise just use what was specified in the message.
+		 *
+		 * When registering change notification on a print server
+		 * handle we always need to send back the id (snum) matching
+		 * the printer for which the change took place.
+		 * For change notify registered on a printer handle,
+		 * this does not matter and the id should be 0.
+		 *
+		 * --jerry
+		 */
 
-		if ( ( p->printer_type == SPLHND_PRINTER )  &&
-		    ( !strequal(msg_group->printername, p->sharename) ) )
-			continue;
+		if ((msg->type == PRINTER_NOTIFY_TYPE) &&
+		    (prn_hnd->printer_type == SPLHND_PRINTER)) {
+			id = 0;
+		} else {
+			id = msg->id;
+		}
 
-		DEBUG(10,("Our printer\n"));
+		/* Convert unix jobid to smb jobid */
 
-		/* allocate the max entries possible */
+		if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
+			id = sysjob_to_jobid(msg->id);
 
-		notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
-		if (!notifies) {
-			return;
+			if (id == -1) {
+				DEBUG(3, ("no such unix jobid %d\n",
+					  msg->id));
+				continue;
+			}
 		}
 
-		/* build the array of change notifications */
+		construct_info_data(&notifies[count],
+				    msg->type, msg->field, id);
 
-		sending_msg_count = 0;
+		switch(msg->type) {
+		case PRINTER_NOTIFY_TYPE:
+			if (printer_notify_table[msg->field].fn) {
+				printer_notify_table[msg->field].fn(msg,
+						&notifies[count], mem_ctx);
+			}
+			break;
 
-		for ( i=0; i<msg_group->num_msgs; i++ ) {
-			SPOOLSS_NOTIFY_MSG	*msg = &messages[i];
+		case JOB_NOTIFY_TYPE:
+			if (job_notify_table[msg->field].fn) {
+				job_notify_table[msg->field].fn(msg,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list