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]




Reply via email to