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 <[email protected]>
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 <[email protected]>
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 <[email protected]>

commit a736385b9749fe127411348ff3e0d1cc4405e47f
Author: Simo Sorce <[email protected]>
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 <[email protected]>

commit 9db2be245e89e14f4c95037f67e7092f298a74f5
Author: Simo Sorce <[email protected]>
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 <[email protected]>

commit 433ac757dcac5841a47db3350865771a5d7301b2
Author: Simo Sorce <[email protected]>
Date:   Wed Jun 30 15:32:15 2010 -0400

    s3-spoolss: Rename Printer_entry to struct printer_handle.
    
    Signed-off-by: Andreas Schneider <[email protected]>

commit 4a8d042afa41510b557e13b2aafcff611a137f28
Author: Simo Sorce <[email protected]>
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 <[email protected]>

commit e257e68b4bcd49c6401b0982e71f3f3085711750
Author: Simo Sorce <[email protected]>
Date:   Wed Jun 30 12:19:41 2010 -0400

    s3-spoolss: Allocate printer entries on the pipe struct.
    
    Signed-off-by: Andreas Schneider <[email protected]>

commit 0e5b1a67d26f99ae6d6f5e05f968dd3107191791
Author: Simo Sorce <[email protected]>
Date:   Wed Jun 30 12:07:44 2010 -0400

    s3-spoolss: Rename session counter structure and use talloc.
    
    Signed-off-by: Andreas Schneider <[email protected]>

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

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

Reply via email to