From cdb71ca5181aa1e06bebe2fffb02dc39de83645e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 10 Oct 2000 21:52:31 +0000 Subject: Fixes to periodically scan printing.tdb in idle time and occasionally on exit. Needed to fix printing.tdb from groving to 300Mb+ if being driven by smbclient clients that never ask for status... (effective DOS attack :-). Jeremy. (This used to be commit 6581066b93a674fadf6f9b92441428d2cc8b4a02) --- source3/include/proto.h | 1 + source3/printing/printing.c | 43 ++++++++++++++++++++++++++++++++++++++++++- source3/smbd/process.c | 6 ++++++ source3/smbd/server.c | 4 ++++ 4 files changed, 53 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 6911c43be7..0ea92c35aa 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1787,6 +1787,7 @@ int print_queue_snum(char *qname); BOOL print_queue_pause(struct current_user *user, int snum, int *errcode); BOOL print_queue_resume(struct current_user *user, int snum, int *errcode); BOOL print_queue_purge(struct current_user *user, int snum, int *errcode); +void process_print_queue(time_t t); #endif /*The following definitions come from profile/profile.c */ diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 9054c8f36a..486ef5d2c7 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -300,6 +300,14 @@ static void print_queue_update(int snum) fstring keystr; TDB_DATA data, key; + /* + * Update the cache time FIRST ! Stops others doing this + * if the lpq takes a long time. + */ + + slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum)); + tdb_store_int(tdb, keystr, (int)time(NULL)); + slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid); unlink(tmp_file); @@ -380,7 +388,11 @@ static void print_queue_update(int snum) key.dsize = strlen(keystr); tdb_store(tdb, key, data, TDB_REPLACE); - /* update the cache time */ + /* + * Update the cache time again. We want to do this call + * as little as possible... + */ + slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum)); tdb_store_int(tdb, keystr, (int)time(NULL)); } @@ -1008,7 +1020,36 @@ BOOL print_queue_purge(struct current_user *user, int snum, int *errcode) } print_cache_flush(snum); + safe_free(queue); return True; } + +/**************************************************************************** + Periodically run a status on all the queues to ensure the tdb doesn't grow. + Note that this will have no effect if the client is doing its own status + queries. This code is here to clean up jobs submitted by non-Windows printer + clients (eg. smbclient) that never do a status check. +****************************************************************************/ + +void process_print_queue(time_t t) +{ + static time_t last_check_time; + int services = lp_numservices(); + print_queue_struct *queue; + print_status_struct status; + int snum; + + if ((t != (time_t)-1) && ((t - last_check_time) < lp_lpqcachetime())) + return; + + last_check_time = t; + + for (snum = 0; snum < services; snum++) { + if (lp_snum_ok(snum) && lp_print_ok(snum) && lp_browseable(snum)) { + (void)print_queue_status(snum, &queue,&status); + safe_free(queue); + } + } +} #undef OLD_NTDOMAIN diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 1599ade12d..9ed83ec88c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -993,6 +993,12 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup )); */ process_pending_change_notify_queue(t); + /* + * Ensure the print queue tdb doesn't grow too + * big by periodically scanning it. + */ + process_print_queue(t); + /* * Now we are root, check if the log files need pruning. */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4442a1f71f..22a95fdd18 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -422,6 +422,10 @@ void exit_server(char *reason) respond_to_all_remaining_local_messages(); + /* Don't do this on every exit... */ + if (sys_random() % 10) + process_print_queue(time(NULL)); + #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); -- cgit