On Fri, 29 Nov 2002, Tomasz Kojm <[EMAIL PROTECTED]> wrote
>On Thu, Nov 28, 2002 at 04:00:08PM -0500, Ed Phillips wrote:
>>
>> How would you make it better? clamd seems to work pretty well for us
>> scanning more than 100,000 messages per day. It hasn't crashed or
>> anything... been running perfectly for a couple of weeks under this load.
>
>
>Currently clamd works like a champ under Linux and Solaris. Amavisd-new
>installation process (with clamscan and clamd) has been described by
>Chris Hastie few days ago:
>
>http://archive.elektrapro.com/clamav.elektrapro.com/users/2002/11/msg00105.html
>
This refers to amavisd-new-20021116. I did post something to the amavis
list about using clamd with 20020517, which you should be able to find
on marc.
Basically, I had the code below in my virus_scan() routine. It was then
necessary to set ONE of $clamd_sockname (set to path to unix socket),
$clamd (set to anything you like - will use INET socket), OR $clamscan
(path to clamscan - uses clamscan), depending on your preference. Only
set a value for ONE of these!!!
You'll note that because of the experimental nature of clamd I've
included a fallback here, so that if clamd fails, scanning falls back to
clamscan. This works with the UNIX socket code - I seem to remember
someone saying it didn't work with the INET stuff. I'm not sure I ever
tested that!
This code is a hack of existing bits of code and I take no
responsibility for it!! In particular, be aware that there is stuff in
the UNIX socket code that I don't understand :) But it did work on my
system until I moved to 20021116.
#
# ClamAV Daemon - unix socket
#
my $clamscan_fallback;
if ($clamd_sockname) {
do_log(2,"Using Clamd - unix socket");
if ($child_task_count == 1) {
unless (socket(\*clamd_sock, AF_UNIX, SOCK_STREAM, 0)) {
do_log(0, "Can't create socket for Clamd: $!");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
}
unless (connect(\*clamd_sock, pack_sockaddr_un $clamd_sockname)) {
do_log (0, "Can't connect to Clamd: $!");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
}
}
my($chkdir) = "SCAN $TEMPDIR/parts/\n";
$SIG{PIPE} = 'IGNORE'; # 'send' to broken pipe throws a signal
my($retries) = 0;
for (;;) { # gracefully handle cases when Sophie child times out
do_log(2, "Sending directory name to Clamd: $TEMPDIR/parts/");
while (!defined(syswrite(\*clamd_sock, $chkdir, length($chkdir)))) {
my($err) = "$!"; my($errn) = 0+$!;
$retries++;
if ($errn != EPIPE && $errn != ENOTCONN) {
do_log(0, "syswrite to Clamd socket failed: $err");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
} else {
if ($retries > 2) { die "Too many retries to talk to Clamd" }
if ($err =~ /^Broken pipe/i) { # slow down a runaway loop
sleep(10 * ($retries-1)) if $retries > 1;
}
do_log( ($retries>1?0:1),
"Re-connecting to Clamd, attempt #$retries");
close(\*clamd_sock); # and ignore status
unless (socket(\*clamd_sock, AF_UNIX, SOCK_STREAM, 0)) {
do_log(0, "Can't create socket for Clamd: $!");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
}
unless (connect(\*clamd_sock, pack_sockaddr_un $clamd_sockname)) {
do_log (0, "Can't connect to Clamd: $!");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
}
}
}
unless (defined(sysread(\*clamd_sock, $output, 256))){
do_log(0, "sysread from Clamd socket failed: $!");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
goto CLAMDEND;
}
last if $output ne '';
do_log( ($retries>1?0:1),
"Failed to get response from Clamd, retrying ($retries)");
sleep 10;
}
if ($output =~ /FOUND$/) { # no errors, a virus was found
$scanner_errors = 0;
@virusname = ($output =~ /: (.+) FOUND/g);
return 1; # 'true' indicates virus found and stops further checking
} elsif ($output =~ /OK$/) { # no errors, no viruses
$scanner_errors = 0;
} elsif ($output =~ /ERROR$/) {
do_log(0,"Virus scanner failure: Clamd - UNKNOWN STATUS (error code:
$output)");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
} else {
do_log(0,"Virus scanner failure: Clamd - UNKNOWN STATUS (error code:
$output)");
do_log(0, " -> try clamscan");
$clamscan_fallback = "/usr/local/bin/clamscan";
}
CLAMDEND:
}
#
# ClamAV Daemon
#
# use IO::Socket;
if ($clamd) {
do_log(2,"Using clamd");
my $sock = IO::Socket::INET->new('127.0.0.1:3310');
# my $sock = IO::Socket::UNIX->new('/var/clamav/clamd');
if (defined $sock) {
$sock->print("SCAN $TEMPDIR/parts\n");
$sock->flush;
chomp($output = $sock->getline);
$sock->close;
do_log(2,$output);
if ($output =~ /FOUND$/) { # no errors, a virus was found
$scanner_errors = 0;
@virusname = ($output =~ /: (.+) FOUND/g);
return 1; # 'true' indicates virus found and stops further checking
} elsif ($output =~ /OK$/) { # no errors, no viruses
$scanner_errors = 0;
} elsif ($output =~ /ERROR$/) {
do_log(0,"Virus scanner failure: ScannerDaemon - UNKNOWN STATUS (error
code: $output) ->Try clamav");
$clamscan_fallback = "/usr/local/bin/clamscan";
} else {
do_log(0,"Virus scanner failure: Clamd - unknown response '$output' ->Try
clamav");
$clamscan_fallback = "/usr/local/bin/clamscan";
}
} else {
do_log(0,"Virus scanner failure: Clamd - can't connect to daemon ->Try
clamav");
$clamscan_fallback = "/usr/local/bin/clamscan";
}
}
#
# clamAV
#
if ($clamscan){
do_log(2,"Using clamav");
$output = qx($clamscan --stdout --disable-summary -r $TEMPDIR/parts);
$errval = retcode($?);
do_log(2, "clamscan: ".$output);
if ($errval == 0) { # no errors, no viruses found
$scanner_errors = 0;
} elsif ($errval == 1) { # no errors, viruses discovered
$scanner_errors = 0;
@virusname = $output =~ /^.*?: (?!Infected Archive)(.*) FOUND$/mg;
@virusname = (undef) if [EMAIL PROTECTED]; # just in case: make list
nonnil
return 1;
} else { # interrupted or some error preventing further execution
do_log(0,"Virus scanner failure: clamav (error code: $errval)");
}
}
#
# clamAV - fallback. This is used if Clamd fails for some reason. A safety net
# as clamd is not entirely stable.
#
if ($clamscan_fallback){
do_log(2,"Using clamav");
$output = qx($clamscan_fallback --stdout --disable-summary -r $TEMPDIR/parts);
$errval = retcode($?);
do_log(2, "clamscan: ".$output);
if ($errval == 0) { # no errors, no viruses found
$scanner_errors = 0;
} elsif ($errval == 1) { # no errors, viruses discovered
$scanner_errors = 0;
@virusname = $output =~ /^.*?: (?!Infected Archive)(.*) FOUND$/mg;
@virusname = (undef) if [EMAIL PROTECTED]; # just in case: make list
nonnil
return 1;
} else { # interrupted or some error preventing further execution
do_log(0,"Virus scanner failure: clamav (error code: $errval)");
}
$clamscan_fallback = "";
}
--
Chris Hastie
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]