#!/usr/pkg/bin/perl
#
# @(#)proc-messages.pl,v 1.41 2010/07/26 22:29:44 kim Exp
#
# Look through /var/adm/messages for things which might be errors (sorted
# by machine) and put them on stdout.
#
# Written 10/2/97 by James Mathiesen
#

%HOST	= ();			# Hash of arrays
@ODD	= ();			# Oddly formatted messages
%DNS	= ();			# Messages about DNS problems
%FTP	= ();			# Messages about FTP problems
%MAIL	= ();			# Rejected mail reasons
%IMAP	= ();			# Messages about IMAP problems
%HORDE	= ();			# Messages about Horde problems
%REJ	= ();			# Recipient counts
%BLOCKED= ();			# Netgear blocked packets
$COUNT	= 0;
$DIV	= '=' x 72 . "\n";

$LOCAL	= '(^|[^.0-9])(127\.0\.0\.\d+'
	. '|10\.\d+\.\d+\.\d+'
	. '|172\.(1[6-9]|2[0-9]|3[01])\.\d+\.\d+'
	. '|192\.168\.\d+\.\d+'
	. '|83\.145\.234\.\d+'
	. '|195\.238\.210\.\d+'
	. '|204\.80\.150\.\d+'
	. '|2001:14b8:0?1e[ef]:'
	. '|2001:1bc8:1011:'
	. '|3ffe:26ff:(00)?10:'
	. '|3ffe:2900:b00c:'
	. ')(\.\d|[^.0-9]|$)|(^|\.)((0\.0\.127'
	. '|10|(1[6-9]|2[0-9]|3[01])\.172|168\.192'
	. '|234\.145\.83'
	. '|210\.238\.195'
	. '|150\.80\.204'
	. ')\.in-addr\.arpa|(4.8.1.0.7.0.5.0.e.f.f.3'
	. '|[ef].e.1.0.8.b.4.1.1.0.0.2'
	. '|1.1.0.1.8.c.b.1.1.0.0.2'
	. '|0.1.0.0.f.f.6.2.e.f.f.3'
	. '|c.0.0.b.0.0.9.2.e.f.f.3'
	. ')\.ip6\.(arpa|int))'
	. '|::1'
	. '|localhost'
	. '|ayfudad\.com'
	. '|convolution\.org'
	. '|d4vision\.com'
	. '|friedman\.to'
	. '|global-wire\.(eu|fi|us)'
	. '|globalwire\.us'
	. '|goodgulf\.org'
	. '|goodi\.org'
	. '|green-sky\.com'
	. '|gw\.(com|net)'
	. '|haka\.iki\.fi'
	. '|hallanvaara\.org'
	. '|huopio\.nu'
	. '|innofinance\.fi'
	. '|jackreacher\.com'
	. '|kashket\.com'
	. '|kurvi\.fi'
	. '|lahi\.com'
	. '|lahikainen\.fi'
	. '|larox\.us'
	. '|laroxflowsys\.com'
	. '|leechild\.net'
	. '|lento29\.iki\.fi'
	. '|lnet\.iki\.fi'
	. '|martikka\.(com|net|org)'
	. '|matsas\.org'
	. '|metachar\.(com|net|org)'
	. '|metdow\.com'
	. '|metzdowd\.com'
	. '|metzgerdowdeswell\.com'
	. '|miskatonic\.edu'
	. '|omm\.iki\.fi'
	. '|partnersandcrime\.com'
	. '|piermont\.com'
	. '|pyry\.org'
	. '|selonen\.(net|org)'
	. '|souminen\.com'
	. '|suntio\.(net|org)'
	. '|suominen\.(com|org|us)'
	. '|tabaee\.com'
	. '|tac\.eu\.org'
	. '|tac\.\w+\.\w{2}\.us'
	. '|tcsh\.org'
	. '|tihku\.(com|net|org)'
	. '|uctp\.net'
	. '|zoulas\.com'
	;

$DEVICE = "(([A-Z]+,)?[A-Za-z]+[0-9]*)";

$PRIVIP = "(10|192[.,]168|172[.,](1[6-9]|2[0-9]|3[01]))[.,][.,0-9]+";

#
# Syslog output look like this:
#	
#	Sep 20 13:08:27 astro.moon.deshaw.com facility[pid]: message
#
# But [pid] is optional.  If there is more than one whitespace character
# after the colon then the message is treated as a continuation of the 
# previous message.  If there is a tab after the hostname than the remainder
# of the line is a continuation of the previous message.
#
# If the word 'last' (as in 'last message repeated') appears in the facility
# position than the message is treated as an independent message associated
# with the previous message.
#
# Ugh, I hope that covers all the possibilities
#
while( <> ) {

    # Get rid of trailing spaces.
    s/\s+$/\n/;

    # Take apart the front of the line
    ( $mon, $dom, $time, $rest ) = split( ' ', $_, 4 );

    # The HP printers are brain dead!
    #	they put multiple spaces between hostname and the facility
    $rest =~ s/^(\S+)[ ][ ]+(\S+)/$1 $2/;

    # HP print server with multiple ports.
    # We need to swap the port number to be after the facility
    $rest =~ s/^(\S+)[ ][ ]+(Port \S+:) (\S+)/$1 $3 $2/;

    # Cisco messages with sequence numbers
    # Remove the sequence number and the date and timestamp after it
    $rest =~ s/^(\S+) \d+: \S{3}\s+\d{1,2}\s+\d{1,2}:\d{2}:\d{2}\.\d{3}: %/$1 %/;

    # Is the first whitespace after the hostname a tab?
    if ( $rest =~ /(\s)/ && $1 eq "\t" ) {
	( $host, $facility, $msg ) = ( $`, '', "\t$'" );
    } else {
	( $host, $facility, $msg ) = split( / /, $rest, 3 );
	if ( $facility eq "last" ) {
	    ( $facility, $msg ) = ( "", "$facility $msg" );
	} elsif ( $facility eq $host ) {
	    $msg =~ m/^(.*\[\d+\]:)(.+)$/;
	    $msg = $2 . "\n";
	    ($facility = $1) =~ s/ /_/g;
	    $facility =~ s/^\[/Netgear[/;
	}
    }

    # SCSI errors on NetBSD produce log entries with a single space
    next if ($facility =~ /^\/netbsd:$/ && $msg eq '');

    # Grab corrupted lines early...
    if ( !defined($msg) || $msg eq '' || $facility =~ /^ / ) {
	push( @ODD, $_ );
	next;
    }

    #
    # Treat continuations of the previous message in the same way we
    # treated the previous message.  This handles "last message 
    # repeated..." and also things like the multi-line named startup
    # message.
    #
    if ( $facility eq '' || $msg =~ /^\s/ ) {
	push( @{$origin{$host}}, "$mon $dom $time $facility$msg" )
	    if defined($origin{$host});
	next;
    }
    undef $origin{$host};

    #
    # Strip out a leading "rpc." in the facility name.
    #
    $facility =~ s/^rpc\.//;

    # These messages are from tcp_wrappers, not the facility itself.
    next if ($msg =~ m!^warning: /etc/hosts.allow, line \d+: (can't verify hostname|host name/(name|address) mismatch): !);

    # Some messages are known to be innocuous...
    (
	( $facility =~ /^unix/          && skipunix($msg) )		||
	( $facility =~ /^\/?netbsd/     && skipunix($msg) )		||
	( $facility =~ /^named-xfer/    && skipnamedxfer($msg) )	||
	( $facility =~ /^named\[/       && skipnamed($msg) )		||
	( $facility =~ /^dhcpd/         && skipdhcpd($msg) )		||
	( $facility =~ /^dhclient/      && skipdhclient($msg) )		||
	( $facility =~ /^amd/           && skipamd($msg) )		||
	( $facility =~ /^nntpd/         && skipnntpd($msg) )		||
	( $facility =~ /^ftpd/          && skipftpd($msg) )		||
	( $facility =~ /^proftpd/       && skipproftpd($msg) )		||
	( $facility =~ /^racoon/        && skipracoon($msg) )		||
	( $facility =~ /^stunnel/       && skipstunnel($msg) )		||
	( $facility =~ /^imap[ds]?/     && skipimapd($msg) )		||
	( $facility =~ /^pop3[ds]?/     && skipimapd($msg) )		||
	( $facility =~ /^ctl_cyrusdb/   && skipcyrus($msg) )		||
	( $facility =~ /^ctl_deliver/   && skipcyrus($msg) )		||
	( $facility =~ /^ctl_mboxlist/  && skipcyrus($msg) )		||
	( $facility =~ /^cyr_expire/    && skipcyrus($msg) )		||
	( $facility =~ /^lmtpunix/      && skipcyrus($msg) )		||
	( $facility =~ /^tls_prune/     && skipcyrus($msg) )		||
	( $facility =~ /^lmtpd/         && skipcyrus($msg) )		||
	( $facility =~ /^deliver/       && skipcyrus($msg) )		||
	( $facility =~ /^ntpdate/       && skipntpdate($msg) )		||
	( $facility =~ /^x?ntpd\[/      && skipntpd($msg) )		||
	( $facility =~ /^rarpd/         && skiprarpd($msg) )		||
	( $facility =~ /^sshd/          && skipsshd($msg) )		||
	( $facility =~ /^supfile/       && skipsupfile($msg) )		||
	( $facility =~ /^statd/         && skipstatd($msg) )		||
	( $facility =~ /^lockd/         && skiplockd($msg) )		||
	( $facility =~ /^netsaint/      && skipnetsaint($msg) )		||
	( $facility =~ /^lpd/           && skiplpd($msg) )		||
	( $facility =~ /^printer/       && skipprinter($msg) )		||
	( $facility =~ /^sendmail/      && skipsendmail($msg) )		||
	( $facility =~ /^postfix/       && skippostfix($msg) )		||
	( $facility =~ /^listserv/      && skiplistserv($msg) )		||
	( $facility =~ /^master/        && skipmaster($msg) )		||
	( $facility =~ /^horde/i        && skiphorde($msg) )		||
	( $facility =~ /^snmpd/         && skipnetsnmp($msg) )		||
	( $facility =~ /^net-snmp/      && skipnetsnmp($msg) )		||
	( $facility =~ /^ucd-snmp/      && skipnetsnmp($msg) )		||
	( $facility =~ /^smartd/        && skipsmartd($msg) )		||
	( $facility =~ /^rpcbind/       && skiprpcbind($msg) )		||
	( $facility =~ /^portmap/       && skiprpcbind($msg) )		||
	( $facility =~ /^identd/        && skipidentd($msg) )		||
	( $facility =~ /^inetd/         && skipinetd($msg) )		||
	( $facility =~ /^rdist/         && skiprdist($msg) )		||
	( $facility =~ /^gated/         && skipgated($msg) )		||
	( $facility =~ /^gdc/           && skipgdc($msg) )		||
	( $facility =~ /^mrouted/       && skipmrouted($msg) )		||
	( $facility =~ /^tftpd/         && skiptftpd($msg) )		||
	( $facility =~ /^squid/         && skipsquid($msg) )		||
	( $facility =~ /^vtund/         && skipvtund($msg) )		||
	( $facility =~ /^pptpd/         && skippptpd($msg) )		||
	( $facility =~ /^jabberd\//     && skipjabberd($msg) )		||
	( $facility =~ /^savecore/      && skipsavecore($msg) )		||
	( $facility =~ /^rsnapshot/     && skiprsnapshot($msg) )	||
	( $facility =~ /^rsynconly/     && skiprsynconly($msg) )	||
	( $facility =~ /(^|\/)websterd/ && skipwebsterd($msg) )		||
	( $facility =~ /^Netgear/       && skipnetgearpacket($msg) )	||
	( $facility =~ /^Hacker_Log/    && skipnetgearpacket($msg) )	||
	( $facility =~ /^DHCP_Request/  && skipnetgeardhcp($msg) )	||
	( $facility =~ /^Telstra/       && skipnetgeartelstra($msg) )	||
	( $facility =~ /^SPA-\d+/       && skipsipura($msg) )		||
	( $facility =~ /^syslog/        && skipsyslogd($msg) )
    ) && next;

    # Origin is the array reference within %HOST which we are to use
    $origin{$host} = ($HOST{$host} ||= []);

    # Put the message in the appropriate list...
    push( @{$origin{$host}}, "$mon $dom $time $facility $msg" );

}

Report("STDOUT");

exit 0;

sub Report
{
    my ( $fd ) = @_;

    Dump($fd,"Badly Formatted Lines",\@ODD);

    foreach $host ( sort(keys(%HOST)) ) {
	Dump($fd,$host,$HOST{$host});
    }

    DumpFrequency($fd,"DNS Warnings",10,\%DNS);
    DumpFrequency($fd,"FTP Warnings",5,\%FTP);
    DumpFrequency($fd,"IMAP Warnings",10,\%IMAP);
    DumpFrequency($fd,"Horde Warnings",5,\%HORDE);
    DumpFrequency($fd,"Rejected mail",5,\%MAIL);

    foreach $rcpt ( sort(keys(%REJ)) ) {
	DumpFrequency($fd,"Rejected senders for ".$rcpt,3,$REJ{$rcpt});
    }

    DumpFrequency($fd,
	"Blocked packets:   Destination     Source",
	15,\%BLOCKED);
}

sub Dump
{
    my ( $fd, $title, $msgs ) = @_;

    # Skip hosts with no messages
    return unless @$msgs;

    # Add some whitespace unless this is the first host
    print $fd "\n\n" if $COUNT++;

    # Dump output (@$msgs has newlines already)
    print $fd $DIV, "$title\n", $DIV, "\n", @$msgs;
}

sub DumpFrequency
{
    my ( $fd, $title, $threshold, $arr ) = @_;

    my ( @OUT, $key );

    local ($FREQREF) = $arr;
    foreach $key ( sort sortbyfrequency keys(%$arr) ) {
	push( @OUT, sprintf( "(%5d) %s", $$arr{$key}, $key ) )
	    unless $$arr{$key} < $threshold;
    }

    Dump( $fd, $title, \@OUT );
}

sub sortbyfrequency
{
    return $$FREQREF{$b} <=> $$FREQREF{$a};
}

sub parsehost
{
    my ($host) = @_;
    local ($addr);
    local ($rest);

    $host =~ tr/[A-Z]/[a-z]/;
    $host =~ s/\[/ /g;
    $host =~ s/\]/ /g;
    $host =~ s/^\s+//;
    $host =~ s/\s+$//;

    ($host, $addr) = split(' ', $host, 2);

    $host = cleanaddr($host);
    $addr = cleanaddr($addr);

    if ($host eq $addr) {
	$host = "unknown";
    }

    $host .= '[' . $addr . ']';

    return $host;
}

sub cleanaddr
{
    my ($addr) = @_;
    $addr =~ s/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/$1/;
    return $addr;
}

sub skipunix
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^NFS server \S+ (not responding still trying|ok)/;

    #
    # These are all messages which appear as part of a machine boot
    #

    # SunOS
    return 1 if $msg =~ /^SunOS Release [.0-9]+ Version/;
    return 1 if $msg =~ /^Copyright/;
    return 1 if $msg =~ /^[pv]ac: enabled/;
    return 1 if $msg =~ /^cpu\d+: [A-Z]+,[A-Z0-9\-]+ \([a-z0-9 ]+\)\s*$/i;
    return 1 if $msg =~ /^mem =/;
    return 1 if $msg =~ /^avail mem =/;
    return 1 if $msg =~ /^Ethernet address =/;
    return 1 if $msg =~ /^root nexus =/;
    return 1 if $msg =~ /^$DEVICE at $DEVICE(:|\Z)/o;
    return 1 if $msg =~ /^$DEVICE (is|on) <?\//o;
    return 1 if $msg =~ /^$DEVICE:\s+[a-z0-9]+-options=/o;
    return 1 if $msg =~ /^$DEVICE:\s+rev [0-9\.]+/o;
    return 1 if $msg =~ /^$DEVICE:\s+FEPS \(Rev Id = \d+\) Found/o;
    return 1 if $msg =~ /^$DEVICE:\s+Using \S+ Transceiver/o;
    return 1 if $msg =~ /^$DEVICE:\s+\d+ \S+ \S*\s*Link Up/o;
    return 1 if $msg =~ /^$DEVICE:\s+Local Ethernet address/o;
    return 1 if $msg =~ /^No contiguous memory requested for [A-Z]+[0-9]*$/;
    return 1 if $msg =~ /^cpu \d+ initialization complete - online$/;
    return 1 if $msg =~ /^boot cpu \(\d+\) initialization complete - online$/;
    return 1 if $msg =~ /^<[a-zA-Z0-9_\- \.]+ cyl \d+/;
    return 1 if $msg =~ /^dump on [\/a-z0-9]+ size [0-9]+K$/;
    return 1 if $msg =~ /^<>$/;
    return 1 if $msg =~ /^pcmcia: no PCMCIA adapters found/;
    return 1 if $msg =~ /^Prestoserve: 0x[0-9]+ bytes on/;
    return 1 if $msg =~ /^MMCODEC: Manufacturer/;

    # NetBSD
    return 1 if $msg =~ /^\[ preserving \d+ bytes of \S+ symbol table \]/;
    return 1 if $msg =~ /^NetBSD [._0-9A-Z]+ \([-A-Z]+\)/;
    return 1 if $msg =~ / All rights reserved.$/;
    return 1 if $msg =~ /^\w+@\S+:\/\S+\/compile\//;
    return 1 if $msg =~ /^cpu\d+: family \d+ model \d+ step \w+/;
    return 1 if $msg =~ /^cpu\d+: AMD .* \(\d+-class\), \d+.\d+ MHz/;
    return 1 if $msg =~ /^cpu\d+: features /;
    return 1 if $msg =~ /^cpu\d+: (I-|L2 )cache \d+ ?KB? /;
    return 1 if $msg =~ /^cpu\d+: physical \d+K instruction /;
    return 1 if $msg =~ /^cpu\d+: (I|D)TLB \d+ \d+ ?[KM]B entries/;
    return 1 if $msg =~ /^cpu\d+: \d+ page colors$/;
    return 1 if $msg =~ /^cpu\d+: calibrating local timer$/;
    return 1 if $msg =~ /^cpu\d+: apic clock running at \d+ MHz$/;
    return 1 if $msg =~ /^cpu\d+: starting$/;
    return 1 if $msg =~ /^cpu\d+: CPU \d+ running$/;
    return 1 if $msg =~ /^cpu\d+: ".+"$/;
    return 1 if $msg =~ /^using \d+ buffers containing \d+ \S+ of memory/;
    return 1 if $msg =~ /^real mem \s*=/;
    return 1 if $msg =~ /^(avail|total) memory \s*=/;
    return 1 if $msg =~ /^((bio|net|tty)mask [0-9a-fx]+\s*)+/;
    return 1 if $msg =~ /^kbc command: /;
    return 1 if $msg =~ /^root file system type: \w+$/;
    return 1 if $msg =~ /^boot device: $DEVICE$/o;
    return 1 if $msg =~ /^bootpath: (\/[a-z]+@[,0-9a-f]+)+$/;
    return 1 if $msg =~ /^mountroot: trying /o;
    return 1 if $msg =~ /^root on $DEVICE[a-z] dumps on $DEVICE[a-z]$/o;
    return 1 if $msg =~ /^root on $DEVICE$/o;
    return 1 if $msg =~ /^root on [0-9a-f:.]+:\S+$/;
    return 1 if $msg =~ /^init: copying out path /;
    return 1 if $msg =~ /^nfs_boot: trying \S+$/;
    return 1 if $msg =~ /^nfs_boot: DHCP server: /;
    return 1 if $msg =~ /^nfs_boot: (gateway|my_(addr|domain|mask|name))=/;
    return 1 if $msg =~ /^(ipl_\S+=[0-9a-f]+ ?)+$/;
    return 1 if $msg =~ /^clock: hz=\d+ /;
    return 1 if $msg =~ /^BIOS32 rev\. \d+ found at [0-9a-fx]+$/;
    return 1 if $msg =~ /^PCI BIOS rev\. \d+\.\d+ found at [0-9a-fx]+$/;
    return 1 if $msg =~ /^PCI BIOS has \d+ Interrupt Routing table entries$/;
    return 1 if $msg =~ /^PCI Exclusive IRQs: /;
    return 1 if $msg =~ /^pcibios: config mechanism /;
    return 1 if $msg =~ /^mpbios: bus \d+ is type \S+$/;
    return 1 if $msg =~ /^PCI IRQ Routing Table rev\. \d+\.\d+ found at [0-9a-fx]+, size \d+ bytes \(\d+ entries\)$/;
    return 1 if $msg =~ /^PCI Interrupt Router at \d+:\d+:\d+/;
    return 1 if $msg =~ /^IPsec: Initialized Security Association Processing\.$/;
    return 1 if $msg =~ /^IP Filter: v[0-9.]+$/;
    return 1 if $msg =~ /^IP Filter: (v[0-9.]+ )?initialized. \s*Default = pass all, Logging = enabled$/;
    return 1 if $msg =~ /^Accounting started$/;
    return 1 if $msg =~ /^Kernelized RAIDframe activated$/;
    return 1 if $msg =~ /^RAIDFRAME: protectedSectors is \d+$/;
    return 1 if $msg =~ /^RAIDFRAME: Configure \(RAID Level \d+\): total number of sectors is \d+ \(\d+ MB\)$/;
    return 1 if $msg =~ /^RAIDFRAME\(RAID Level \d+\): Using \d+ floating recon bufs with no head sep limit$/;
    return 1 if $msg =~ /^$DEVICE: Component \S+ being configured at row: /o;
    return 1 if $msg =~ / at $DEVICE not configured$/o;
    return 1 if $msg =~ / at $DEVICE dev \d+ function \d+ not configured$/o;
    return 1 if $msg =~ / port [-\/,0-9a-fx]+( (irq|drq) [0-9,]+)* not configured$/;
    return 1 if $msg =~ /^\S+: loaded into \S+ at slot \d+$/;
    return 1 if $msg =~ /^$DEVICE \(root\)/o;
    return 1 if $msg =~ /^$DEVICE: enabling$/o;
    return 1 if $msg =~ /^$DEVICE at $DEVICE (apid|bus|channel|dev|drive|irq|mux|phy|slot|targ(et)?|unit) \d+(:|\s|$)/o;
    return 1 if $msg =~ /^$DEVICE at $DEVICE( (ioaddr|iomem|port) [-\/,0-9a-fx]+|( (irq|drq) [0-9,]+))+(:|\Z)/o;
    return 1 if $msg =~ /^$DEVICE at $DEVICE \((aux|kbd) slot\)$/o;
    return 1 if $msg =~ /^$DEVICE at $DEVICE \(\S+(@(i[0-9a-f]+)?)?\)(: |$)/o;
    return 1 if $msg =~ /^$DEVICE targ(et)? [0-9a-f]+:/o;
    return 1 if $msg =~ /^$DEVICE\($DEVICE[:0-9]+\): using \S+ mode \d+,/o;
    return 1 if $msg =~ /^$DEVICE\($DEVICE[:0-9]+\): max sync rate /o;
    return 1 if $msg =~ /^$DEVICE: (Cogent|Creative|ESS Technology|Hauppauge|Intel|Promise|SigmaTel|Silicon|model) \S+/o;
    return 1 if $msg =~ /^$DEVICE: ac97: .* codec; /o;
    return 1 if $msg =~ /^$DEVICE: ac97: ext id \d+</o;
    return 1 if $msg =~ /^$DEVICE: .* ATA\d+ controller$/o;
    return 1 if $msg =~ /^$DEVICE: .* \S+-\S+ Bridge \(rev. [0-9a-fx]+\)$/o;
    return 1 if $msg =~ /^$DEVICE: .* product [0-9a-fx]+ \(rev\. [0-9a-fx]+\)$/o;
    return 1 if $msg =~ /^$DEVICE: Detected a \S+ at [0-9a-fx]+$/o;
    return 1 if $msg =~ /^$DEVICE: i\/o space, memory space enabled/o;
    return 1 if $msg =~ /^$DEVICE: no ISA Plug 'n Play devices found$/o;
    return 1 if $msg =~ /^$DEVICE: misconfigured as apic \d+$/o;
    return 1 if $msg =~ /^$DEVICE: remapped to apic \d+$/o;
    return 1 if $msg =~ /^$DEVICE: pa [0-9a-fx]+, version \d+, \d+ pins$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ version [0-9.]+$/o;
    return 1 if $msg =~ /^$DEVICE: .* [EOU]HCI root hub, /o;
    return 1 if $msg =~ /^$DEVICE: companion controllers, \d+ ports each: /o;
    return 1 if $msg =~ /^$DEVICE: single transaction translator$/o;
    return 1 if $msg =~ /^$DEVICE: vendor [0-9a-fx]+ product [0-9a-fx]+ /o;
    return 1 if $msg =~ /^$DEVICE: random number generator enabled($|, )/o;
    return 1 if $msg =~ /^$DEVICE: \d+ ports /o;
    return 1 if $msg =~ /^$DEVICE: using irq \d+ for /o;
    return 1 if $msg =~ /^$DEVICE: ((async|parity|\d+- transfers)[, ]*)+$/o;
    return 1 if $msg =~ /^$DEVICE: waiting \d+ seconds for devices to /o;
    return 1 if $msg =~ /^$DEVICE: unlocking mailbox interface$/o;
    return 1 if $msg =~ /^$DEVICE: (\S+ (channel )?)?interrupting at ($DEVICE pin \d+ \()?irq \d+\)?$/o;
    return 1 if $msg =~ /^$DEVICE: bus-master DMA support present$/o;
    return 1 if $msg =~ /^$DEVICE: i\/o enabled, memory enabled$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ channel (configured|wired) to /o;
    return 1 if $msg =~ /^$DEVICE: disabling \S+ channel \(no drives\)$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ channel ignored \(disabled\)$/o;
    return 1 if $msg =~ /^$DEVICE: device disabled \(at device\)$/o;
    return 1 if $msg =~ /^$DEVICE: \d+ H.W CCBs(, (parity|sync|tagged queueing)*)$/o;
    return 1 if $msg =~ /^$DEVICE: [a-z0-9\/]+:?( \S+)+ Channel( [A-Z])?, SCSI Id=\d+, \d+(\/\d+)? SCBs$/o;
    return 1 if $msg =~ /^$DEVICE: ((sync|parity)(,\s*)?)+/o;
    return 1 if $msg =~ /^OptionMode = \d$/;
    return 1 if $msg =~ /^$DEVICE: target \d+: sync negotiation$/o;
    return 1 if $msg =~ /^$DEVICE: target \d+ synchronous at [.0-9]+MHz,/o;
    return 1 if $msg =~ /^$DEVICE: target \d+ using \S+ transfers/o;
    return 1 if $msg =~ /^$DEVICE: target \d+ using tagged queuing$/o;
    return 1 if $msg =~ /^$DEVICE: \d+-bits? data port/o;
    return 1 if $msg =~ /^$DEVICE: \d+ ports, Firmware \S+ \S+, BIOS /o;
    return 1 if $msg =~ /^$DEVICE: Monitor \S+ \S+, PCB /o;
    return 1 if $msg =~ /^$DEVICE: port \d+: /o;
    return 1 if $msg =~ /^$DEVICE: drive supports /o;
    return 1 if $msg =~ /^$DEVICE: \d+ ?[KMGT]B, \d+ cyl, \d+ head, \d+ sec, \d+ bytes\/sec/o;
    return 1 if $msg =~ /^$DEVICE: using \d+-sector \d+-bit \S+ transfers, \S+ addressing$/o;
    return 1 if $msg =~ /^$DEVICE: density code [0-9a-fx]+,/o;
    return 1 if $msg =~ /^$DEVICE: \S+ \S+, Ethernet address:? [:0-9a-fx]+$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ Ethernet \(\d+-bit\)$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ rev\. \S+, address [:0-9a-fx]+, media \S+$/o;
    return 1 if $msg =~ /^$DEVICE: ((Ethernet|MAC) )?address:? [:0-9a-fx]+$/o;
    return 1 if $msg =~ /^$DEVICE: OUI [0-9a-fx]+, model [0-9a-fx]+, rev\. \d+/o;
    return 1 if $msg =~ /^$DEVICE: ((10+base[-FDTX]+|auto)[, ]*)+$/o;
    return 1 if $msg =~ /^$DEVICE: setting full duplex\.?$/o;
    return 1 if $msg =~ /^$DEVICE: strapped to slave mode, /o;
    return 1 if $msg =~ /^$DEVICE: enabling (Full|Half) Duplex \S+ port$/o;
    return 1 if $msg =~ /^$DEVICE: \d+ receive buffers, \d+ transmit buffers$/o;
    return 1 if $msg =~ /^$DEVICE: supplying EUI64: [:0-9a-fx]+$/o;
    return 1 if $msg =~ /^$DEVICE: starting DAD for [:0-9a-fx]+$/o;
    return 1 if $msg =~ /^$DEVICE: DAD complete for [:0-9a-fx]+ - no duplicates found$/o;
    return 1 if $msg =~ /^$DEVICE: not multicast capable, IPv6 not enabled$/o;
    return 1 if $msg =~ /^$DEVICE: \d+[KMGT]B (\w|-)+ FIFO,/o;
    return 1 if $msg =~ /^$DEVICE:( (AES|3?DES),)+ \d+KB dram, interrupting /o;
    return 1 if $msg =~ /^$DEVICE: (rogue, )?drive empty$/o;
    return 1 if $msg =~ /^$DEVICE: \S+ not connected$/o;
    return 1 if $msg =~ /^$DEVICE: (A\/C|battery charge) state: /o;
    return 1 if $msg =~ /^$DEVICE: ((color|generic|\S+-kbd|\d+ (col|scr)|\[R[.0-9]+\])(,\s*)?)+$/o;
    return 1 if $msg =~ /^$DEVICE: connecting to $DEVICE$/o;
    return 1 if $msg =~ /^$DEVICE: attached to \S+$/o;
    return 1 if $msg =~ /^$DEVICE: $DEVICE glued to $DEVICE \(console\)$/o;
    return 1 if $msg =~ /^$DEVICE: screen [-0-9]+ added /o;
    return 1 if $msg =~ /^$DEVICE at $DEVICE kbdmux \d+(: console)?($| )/o;
    return 1 if $msg =~ /^$DEVICE: console$/o;
    return 1 if $msg =~ /^$DEVICE: joystick connected$/o;

    #
    # Other innocuous messages
    #
    return 1 if $msg =~ /^pseudo-device: $DEVICE$/oi;

    #
    # NFS noise
    #
    return 1 if $msg =~ /^NFS/ && $msg =~ /Stale NFS/;
    return 1 if $msg =~ /^NFS/ && $msg =~ /No space left/;
    return 1 if $msg =~ /^\(file handle:/;
    return 1 if $msg =~ /^(File|User): userid=/;

    #
    # Full file-systems are tracked by another process
    #
    return 1 if $msg =~ /file system full/;

    #
    # Sync message may-or-may-net be followed by something interesting
    #
    return 1 if $msg =~ /^syncing file systems\.\.\.(\s*\[\d+\])*\s*(\Z|Sun|cpu|done)/;

    return 0;
}

sub skipnamed
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^ns_(forw|resp): query\(.*\) All possible A RR's lame$/;
    return 1 if $msg =~ /^(USAGE|NSTATS|XSTATS) \d+ \d+/;
    return 1 if $msg =~ /^Cleaned cache of \d+ RRsets?$/;
    return 1 if $msg =~ /^approved [AI]XFR from \S+ for \S+$/;
    return 1 if $msg =~ /^zone transfer \([AI]XFR\) of \S+ \(\S+\) to \S+$/;
    return 1 if $msg =~ /^starting|reloading/;
    return 1 if $msg =~ /^found \d+ CPUs?, using \d+ worker threads?/;
    return 1 if $msg =~ /^Ready to answer queries/;
    return 1 if $msg =~ /^((hint|master|slave) z|Z)one \S+ \S+ (loaded|removed)/;
    return 1 if $msg =~ /^Sent NOTIFY for /;
    return 1 if $msg =~ /^suppressing duplicate notify /;
    return 1 if $msg =~ /^zone \S+: sending notifies \(serial \S+\)$/;
    return 1 if $msg =~ /^zone \S+: (loaded|transferr?ed) serial \S+$/;
    return 1 if $msg =~ /^zone \S+: notify from \S+: zone is up to date$/;
    return 1 if $msg =~ /^zone \S+: Transfer started.$/;
    return 1 if $msg =~ /^received notify for zone \S+$/;
    return 1 if $msg =~ /^client \S+: (view \S+: )?received notify for zone \S+$/;
    return 1 if $msg =~ /^client \S+: (view \S+: )?transfer of \S+:([- ]([AI]XFR|style))+ (ended|started)$/;
    return 1 if $msg =~ /^transfer of \S+ from \S+: end of transfer$/;
    return 1 if $msg =~ /^owner name "\S+" \S+ \S+ is invalid - proceeding anyway$/;
    return 1 if $msg =~ /^enforced delegation-only for \S+ /;
    return 1 if $msg =~ /^running$/;
    return 1 if $msg =~ /^listening on /;
    return 1 if $msg =~ /^using \d+ CPUs?$/;
    return 1 if $msg =~ /^loading configuration from \S+$/;
    return 1 if $msg =~ /^command channel listening on \S+$/;
    return 1 if $msg =~ /^[Ff]orwarding source address is /;
    return 1 if $msg =~ /^no IPv6 interfaces found$/;

    if ( $msg =~ / points to (a )?CNAME / ) {
	$DNS{$msg}++ if $msg =~ /$LOCAL/oi;
	return 1;
    }

    if ( $msg =~ /^(bad referral|invalid RR type|Lame server|ns_resp: TCP truncated:|Response from unexpected source|unrelated additional info)/ ) {
	$DNS{$msg}++ if $msg =~ /$LOCAL/oi;
	return 1;
    }

    if ( $msg =~ s/^client (\S+)#\d+:( view \S+:)? update( forwarding)? (\S+) denied$/denied update for $3 from $1/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ s/^client (\S+)#\d+:( view \S+:)? updating zone (\S+): update (failed|unsuccessful): .*$/failed update for $2 from $1/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ s/^client (\S+)#\d+: (view \S+: )?zone transfer (\S+) denied$/transfer to $1: DENIED/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ /^(denied|unapproved) ([AI]XFR|update) from \S+ for "?(\S+)"?/ ) {
	$msg =~ s/(\[[.0-9]+\])\.[0-9]+/$1/;
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ /^Received NOTIFY answer( \(!?AA\))? from \S+ for "?(\S+)/ ) {
	$DNS{$msg}++ if $2 !~ /$LOCAL/oi;
	return 1;
    }

    if ( $msg =~ /^rcvd NOTIFY\(([^,]+), \S+, \S+\) from \S+$/ ) {
	$DNS{$msg}++ if $1 !~ /$LOCAL/oi;
	return 1;
    }

    if ( $msg =~ /^zone \S+: (refused notify from non-master: \S+)#\d+$/ ) {
	$DNS{"$1\n"}++;
	return 1;
    }

    if ( $msg =~ /^(NOTIFY\(\S+\) from non-master server) \(zone \S+\), from (\[\S+\])\.\d+$/ ) {
	$DNS{"$1 $2\n"}++;
	return 1;
    }

    if ( $msg =~ /^((Err.TO getting serial. for|zoneref: Masters for secondary zone) |rcvd NOTIFY for \S+, name not one of our zones)/ ) {
	$DNS{$msg}++;
	return 1;
    }

    # dual logged
    return 1 if $msg =~ /^zone \S+: refresh: retry limit for master \S+ exceeded /;
    if ( $msg =~ s/^transfer of \S+ (from \S+)#\d+(: .*)$/transfer $1$2/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ s/^zone \S+: refresh: (failure trying master \S+: .*)$/$1/ ) {
	$DNS{$msg}++;
	return 1;
    }

    return 0;
}

sub skipnamedxfer
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^connect\((\d+|\.)+\) for zone \S+ failed: /;
    return 1 if $msg =~ /^send AXFR query \d+ to (\d|\.)+$/;

    if ( $msg =~ /not authoritative/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ /no SOA found/ ) {
	$DNS{$msg}++;
	return 1;
    }

    if ( $msg =~ /^premature EOF, fetching / ) {
	$DNS{$msg}++;
	return 1;
    }

    return 0;
}

sub skipimapd
{
    my ( $msg ) = @_;
    local ( $host );

    return 1 if $msg =~ /^client id: /;
    return 1 if $msg =~ /^no user in db$/;
    return 1 if $msg =~ /^login:( \S+){2,3} (APOP|CRAM-MD5|PLAIN|plain(text)?)(\+TLS)?\s*(User logged in)?$/;
    return 1 if $msg =~ /^starttls: (SSL|TLS)v\d+ with cipher \S+ \(\d+\/\d+ bits( (new|reused))?\) no authentication\s*$/;
    return 1 if $msg =~ /^open: user \S+ opened \S+$/;
    return 1 if $msg =~ /^skiplist: (checkpoint|recover)ed \S+ \(\d+ records?, \d+ bytes?\) in \d+ seconds?$/;
    # connection reset is usually from failed stunnel negotiation
    return 1 if $msg =~ /^PROTERR: Connection reset by peer$/;
    return 1 if $msg =~ /^Connection (reset by peer|timed out), closing connection$/;
    return 1 if $msg =~ /^Fatal error: tls_start_servertls\(\) failed/;
    return 1 if $msg =~ /^PROTERR: idle for too long$/;
    return 1 if $msg =~ /^idle for too long, closing connection$/;
    return 1 if $msg =~ /^(DBERROR db3|DBMSG): \d+ lockers$/;

    if ( $msg =~ /^badlogin: (\S+) (\S+) .+ authentication failure($|[: ].+)/ ) {
	$host = parsehost("$1 $2");
	if (defined($3)) {
	    $msg = $3;
	    if ( $msg =~ / realm changed($|:)/ ) {
		$IMAP{"LOGIN FAILED: from $host (realm changed)\n"}++;
		return 1;
	    }
	}
	$IMAP{"LOGIN FAILED: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^badlogin: (\S+) (\S+) \S+ \S+ SASL\(-?\d+\): user not found: checkpass failed$/ ) {
	$host = parsehost("$1 $2");
	$IMAP{"LOGIN FAILED: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^(\S+ TLS negotiation failed: \S+)( \S+)?$/ ) {
	$IMAP{$1}++;
	return 1;
    }

    if ( $msg =~ /^\S+ failed: / ) {
	$IMAP{$msg}++;
	return 1;
    }

    return 0;
}

sub skipntpd
{
    my ( $msg ) = @_;

    # sync to double digit stratum is worth seeing
    return 1 if $msg =~ /^synchronized to \S+, stratum=\d+$/;
    return 1 if $msg =~ /^Previous time adjustment/;
    return 1 if $msg =~ /^time reset/;
    return 1 if $msg =~ /^sendto\(\S+\): Host is down/;
    return 1 if $msg =~ /^sendto\(\S+\): No route to host/;
    return 1 if $msg =~ /^Connection re-established to /;
    return 1 if $msg =~ /^x?ntpd [0-9]\S+ /;
    return 1 if $msg =~ /^[0-9]\S+ \d+-/; # another version announcement
    return 1 if $msg =~ /^tickadj = \d+,/;
    return 1 if $msg =~ /^precision = (\d|\.)+ usec$/;
    return 1 if $msg =~ /^using kernel phase-lock loop \d+$/;
    return 1 if $msg =~ /^kernel time sync (disabled|enabled|status) \d+$/;
    return 1 if $msg =~ /^frequency initialized \S+( PPM)? from /;
    return 1 if $msg =~ /^read drift of \S+ from /;
    return 1 if $msg =~ /^\S+ exiting on signal \d+$/;
    return 1 if $msg =~ /^no IPv6 interfaces found$/;

    return 0;
}

sub skiprarpd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^$DEVICE: [:0-9a-fA-F]+$/o;

    return 0;
}

sub skipsshd
{
    my ( $msg ) = @_;

    if ( $msg =~ /^Accepted rsa for ROOT from (\S+) port \d+$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
	return 0;
    }

    return 1 if $msg =~ /^connect from \S+$/;
    return 1 if $msg =~ /^Accepted rsa for \S+ from \S+ port \d+$/;
    return 1 if $msg =~ /^\S+ from \S+ \(RSA user authentication accepted\)$/;

    $msg =~ s/^log: //;

    return 1 if $msg =~ /^Connection from \S+ port \d+$/;
    return 1 if $msg =~ /^Closing connection to \S+$/;
    return 1 if $msg =~ /^RSA authentication for \S+ accepted\.$/;
    return 1 if $msg =~ /^Kerberos authentication accepted \S+ for account \S+ from \S+$/;
    return 1 if $msg =~ /^executing remote command as (root:|user) /;
    return 1 if $msg =~ /^Generating (new )?\d+ bit RSA key\.$/;
    return 1 if $msg =~ /^RSA key generation complete\.$/;
    return 1 if $msg =~ /^Server listening on ([0-9a-f.:]+ )?port \d+\.$/;

    $msg =~ s/^fatal: //;

    return 1 if $msg =~ /^Connection closed by remote host\.$/;
    return 1 if $msg =~ /^Read [^:]+: Connection reset by peer$/;
    return 1 if $msg =~ /^Read [^:]+: Connection timed out$/;
    return 1 if $msg =~ /^Did not receive ident string\.$/;

    if ( $msg =~ /^ROOT LOGIN as \S+ from (\S+)$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    return 0;
}

sub skipsupfile
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Fileserver is busy/;
    return 1 if $msg =~ /^SUP File Server Version .* starting at /;

    return 0;
}

sub skiptftpd
{
    my ( $msg ) = @_;

    if ( $msg =~ /^(\S+): read request for \S+: success$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    return 0;
}

sub skipsquid
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Squid Parent: child process \d+ started$/;
    return 1 if $msg =~ /^Squid Parent: child process \d+ exited with status 0$/;

    return 0;
}

sub skipsavecore
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^no core dump( \(no dumpdev\))?$/;

    return 0;
}

sub skipdhcpd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^DHCPINFORM from \S+ via \S+$/;
    return 1 if $msg =~ /^DHCPACK to \S+$/;
    return 1 if $msg =~ /^DHCPREQUEST for \S+( \(\S+\))? from \S+ (\(\S+( \S+)*\) )?via \S+$/;
    return 1 if $msg =~ /^DHCPACK on \S+ to \S+ (\(\S+( \S+)*\) )?via \S+$/;
    return 1 if $msg =~ /^DHCPDISCOVER from \S+ (\(\S+( \S+)*\) )?via \S+$/;
    return 1 if $msg =~ /^DHCPOFFER on \S+ to \S+ (\(\S+( \S+)*\) )?via \S+$/;
    return 1 if $msg =~ /^DHCPRELEASE of \S+ from \S+ (\(\S+( \S+)*\) )?via \S+ \(found\)$/;
    return 1 if $msg =~ /^data: lease_time: lease ends at 0 when it is now \d+$/;
    return 1 if $msg =~ /^Wrote \d+ (deleted|new dynamic) host decls to leases file\.$/;
    return 1 if $msg =~ /^Wrote \d+ leases to leases file\.$/;

    return 0;
}

sub skipdhclient
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^DHCPREQUEST on \S+ to \S+ port \d+$/;
    return 1 if $msg =~ /^DHCPACK from \S+$/;
    return 1 if $msg =~ /^bound to \S+ -- renewal in \d+ seconds\.$/;
    return 1 if $msg =~ /^DHCPDISCOVER on \S+ to \S+ port \d+ interval \d+$/;
    return 1 if $msg =~ /^Trying medium /;

    return 0;
}

sub skiplpd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^restarted$/;

    return 0;
}

sub skipprinter
{
    my ( $msg ) = @_;

    # strip the port number for further checks
    $msg =~ s/^Port \[\d\]: //;

    return 1 if $msg =~ /^output full/;
    return 1 if $msg =~ /^paper (jam|out|cleared)/;
    return 1 if $msg =~ /^offline/;
    return 1 if $msg =~ /^error cleared/;
    return 1 if $msg =~ /^cover\/door open/;
    return 1 if $msg =~ /^peripheral low-power state/;
    return 1 if $msg =~ /^registered system name /;

    return 0;
}

sub skipstatd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^statd: cannot talk to statd/;
    return 1 if $msg =~ /^statd: host \S+ is not responding/;
    return 1 if $msg =~ /^statd: Starting$/;

    return 0;
}

sub skiplockd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^lockd: Starting$/;

    return 0;
}

sub skipnetsaint
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^HOST ALERT: \S+;\S+;SOFT;\d+;/;
    return 1 if $msg =~ /^SERVICE ALERT: \S+;\S+;\S+;SOFT;\d+;/;
    return 1 if $msg =~ /^(HOST|SERVICE) NOTIFICATION: /;
    return 1 if $msg =~ /^Auto-save of retention data completed successfully. *$/;
    return 1 if $msg =~ /^LOG ROTATION: DAILY *$/;
    return 1 if $msg =~ /^NetSaint \S+ starting\.\.\. /;
    return 1 if $msg =~ /^Finished daemonizing\.\.\. /;
    return 1 if $msg =~ /^Entering active mode\.\.\. *$/;

    return 0;
}

sub skipntpdate
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^(step|adjust) time/;

    return 0;
}

sub skipgated
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^KRT READ REMNANT /;
    return 1 if $msg =~ /^NOTIFICATION (received from|sent to) \S+ \((External AS \d+|proto)\): code (4|6) /;
    return 1 if $msg =~ /^bgp_pp_recv: dropping \S+ \S+, connection collision\(\d+\) prefers \S+ \(External AS \d+\)$/;
    return 1 if $msg =~ /^task_reconfigure re-?initializing (from \S+|done)$/;
    return 1 if $msg =~ /^trace_do_dump: ((processing|dump|completed) )+to \S+$/;
    return 1 if $msg =~ /^Start gated\[\d+\] version /;
    return 1 if $msg =~ /^Commence routing updates$/;

    return 0;
}

sub skipgdc
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^performing a "gdc \S+" command for user root$/;

    return 0;
}

sub skipmrouted
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^warning - duplicate prune received /;
    return 1 if $msg =~ /^mrouted version /;

    return 0;
}

sub skippostfix
{
    my ( $msg ) = @_;
    local ( $tmp );
    local ( $host );
    local ( $sndr );
    local ( $rcpt );
    local ( $rest );

    return 1 if $msg =~ /^(dis)?connect (from|to) /;
    return 1 if $msg =~ /^\S+: (client|from|(resent-)?message-id|uid)=/;
    return 1 if $msg =~ /^warning: [.0-9]+: address not listed for hostname /;
    return 1 if $msg =~ /^warning: [.0-9]+: hostname \S+ verification failed: /;
    return 1 if $msg =~ /^warning: valid_hostname: numeric hostname: /;
    return 1 if $msg =~ /^refreshing the Postfix mail system$/;
    return 1 if $msg =~ /^reload configuration$/;
    return 1 if $msg =~ /^(lookup )?table has changed -- exiting$/;
    return 1 if $msg =~ /^daemon started$/;
    return 1 if $msg =~ /^st(art|opp)ing the Postfix mail system$/;
    return 1 if $msg =~ /^terminating on signal 15$/;

    # ignore debugging of SMTP session
    return 1 if $msg =~ /^[<>] /;

    if ( $msg =~ /^\S+: to=(\S+), .*, status=(\S+) / ) {
	$tmp = $2;
	( $rcpt = $1 ) =~ tr/[A-Z]/[a-z]/;
	$rcpt =~ s/^<(.*)>$/$1/;
	return 1 if $tmp =~ /^(deferred|sent)$/;
	$MAIL{$tmp.': '.$rcpt."\n"}++ if $rcpt =~ /$LOCAL/oi;
	return 1;
    }

    if ( $msg =~ /^lost connection after (\S+) from (\S+)$/ ) {
	$tmp = $1;
	$host = parsehost($2);
	return 1 if $tmp =~ /^(RCPT|RSET)$/;
	$MAIL{'lost connection: '.$host."\n"}++;
	return 1;
    }

    if ( $msg =~ /^timeout after (\S+) from (\S+)$/ ) {
	$tmp = $1;
	$host = parsehost($2);
	return 1 if $tmp =~ /^(RCPT|RSET)$/;
	$MAIL{'timeout: '.$host."\n"}++;
	return 1;
    }

    if ( $msg =~ /^too many errors after (\S+) from (\S+)$/ ) {
	$tmp = $1;
	$host = parsehost($2);
	return 1 if $tmp =~ /^(RCPT|RSET)$/;
	return 1 if $host =~ /^unknown\[/;
	$MAIL{'too many errors: '.$host."\n"}++;
	return 1;
    }

    if ( $msg =~ /^reject: \S+ from (\S+): \d+ (.+); from=<(.*)> to=<(.*)>$/ ) {
	$host = parsehost($1);
	$tmp = $2;
	$sndr = $3;
	( $rcpt = $4 ) =~ tr/[A-Z]/[a-z]/;

	#
	# Uninteresting rejects (no per-recipient report)
	#

	if ( $tmp =~ /^[^:]+: User unknown$/) {
	    $MAIL{'User unknown: '.$rcpt."\n"}++;
	    return 1;
	}

	# Collect data for per-recipient report
	if ( ($rcpt !~ /^\d/) && ($sndr !~ /^$/) ) {
	    $REJ{$rcpt}{$sndr."\n"}++;
	}

	#
	# Interesting rejects, per-recipient
	#

	if ( $tmp =~ /^Client host rejected: ([^,]+)/) {
	    $MAIL{'reject client: '.$1."\n"}++;
	    return 1;
	}
	if ( $tmp =~ /^[^:]+: (\S+) address rejected: (.+)$/) {
	    ( $tmp = $1 ) =~ tr/[A-Z]/[a-z]/;
	    $MAIL{'reject '.$tmp.': '.$2."\n"}++;
	    return 1;
	}
	if ( $tmp =~ /^Service unavailable\; \S+ blocked using ([^,]+)/) {
	    $MAIL{'reject blocked: '.$1."\n"}++;
	    return 1;
	}
	if ( $tmp =~ /^[^:]+: Relay access denied$/) {
	    $MAIL{'reject relay: '.$rcpt."\n"}++;
	    return 1;
	}
	$MAIL{'reject other: '.$host."\n"}++;
	return 1;
    }

    return 0;
}

sub skipsendmail
{
    my ( $msg ) = @_;
    local ( $tmp );

    return 1 if $msg =~ /^\S+: (from|to)=/;
    return 1 if $msg =~ /^\S+: clone \S+, owner=\S+$/;
    return 1 if $msg =~ /^\S+: \S+: (DSN|postmaster notify): (Host|User) unknown/;
    return 1 if $msg =~ /^\S+: \S+: (DSN|return to sender): Cannot send message within \d+ \S+$/;
    return 1 if $msg =~ /^\S+: Authentication-Warning: \S+: \S+ set sender to /;
    return 1 if $msg =~ /NOQUEUE: Null connection from /;
    return 1 if $msg =~ /NOQUEUE: SYSERR: .+: Broken pipe$/;
    return 1 if $msg =~ /malformed address: <\@>/;
    return 1 if $msg =~ /553 <\@>/;
    return 1 if $msg =~ /[Tt]oo many hops/;
    return 1 if $msg =~ /timeout waiting for input from \S+ during client /;
    return 1 if $msg =~ /timeout waiting for input from \S+ during server cmd read/;
    return 1 if $msg =~ /lost input channel from /;
    return 1 if $msg =~ /collect: I\/O error .*: Connection reset by /;
    return 1 if $msg =~ /^\S+: \d+ aliases, longest \d+ bytes, \d+ bytes total$/;
    return 1 if $msg =~ /^alias database \S+ rebuilt by root$/;
    return 1 if $msg =~ /^starting daemon \S+: /;

    if ( $msg =~ /^\S+: (.*)\.\.\. User unknown$/ ) {
	( $tmp = $1 ) =~ tr/[A-Z]/[a-z]/;
	$tmp =~ s/^<(.*)>$/$1/;
	$MAIL{'User unknown: '.$tmp."\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+: ruleset=check_(mail|rcpt), .*, reject=\d+ .*\.\.\. (.+)$/ ) {
	$MAIL{$2."\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+: ruleset=check_relay, .*, reject=\d+ / ) {
	if ( $msg =~ /\/dul\/$/ ) {
	    $tmp = "DUL block";
	} elsif ( $msg =~ /\/rbl\/$/ ) {
	    $tmp = "RBL block";
	} else {
	    return 0;
	}
	$MAIL{$tmp."\n"}++;
	return 1;
    }

    return 0;
}

sub skiplistserv
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Mail to list \S+ from .+ - Refused, /;
    return 1 if $msg =~ /^can't open .+\.u$/;
    return 1 if $msg =~ /^(System|Total|User) CPU time: /;
    return 1 if $msg =~ /^% CPU used: /;

    return 0;
}

sub skipmaster
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^process started$/;
    return 1 if $msg =~ /^ready for work$/;
    return 1 if $msg =~ /^got SIGHUP$/;

    return 0;
}

sub skiphorde
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^PHP Warning:  *Retrying \S+ authentication after authentication failure /;
    return 1 if $msg =~ /^PHP Warning:  *Can not authenticate to IMAP server: authentication failure /;

    if ( $msg =~ /^\[imp\] FAILED LOGIN (\S+) to \S+:\S+ as \S+ / ) {
	$HORDE{"LOGIN FAILED: from $1\n"}++;
	return 1;
    }

    return 0;
}

sub skiprpcbind
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^connect from (127\.0\.0\.1|::1) to (getaddrlist|null|set|unset)\(/;

    if ( $msg =~ /connect from (\S+) to getport(\/addr)?\((amd|nfs|mountd|rquotad|rstatd|rusersd|ypserv)\)$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    if ( $msg =~ /connect from (\S+) to null\(\)$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    return 0;
}

sub skipnetsnmp
{
    my ( $msg ) = @_;

    if ( $msg =~ /Connection from (TCP|UDP): \[(\S+)\]:\d+/ ) {
	return 1 if $2 =~ /$LOCAL/oi;
    }

    if ( $msg =~ /(Connection|Received SNMP packet.s.) from (\S+)/ ) {
	return 1 if $2 =~ /$LOCAL/oi;
    }

    return 1 if $msg =~ /^(NET|UCD)-SNMP version \S+\s*$/;
    return 1 if $msg =~ /^Received TERM or STOP signal/;
    return 1 if $msg =~ /^Reconfiguring daemon\s*$/;

    return 0;
}

sub skipsmartd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Device: \S+, SMART Usage Attribute: \d+ \S+ changed from \d+ to \d+$/;
    return 1 if $msg =~ /^Device: \S+, is SMART capable\. Adding to "monitor" list\.$/;
    return 1 if $msg =~ /^Device: \S+,( not)? found in smartd database\.$/;
    return 1 if $msg =~ /^Device: \S+, opened$/;
    return 1 if $msg =~ /^Home page is /;
    return 1 if $msg =~ /^Monitoring \d+ ATA and \d+ SCSI devices$/;
    return 1 if $msg =~ /^No configuration file \S+ found, scanning devices$/;
    return 1 if $msg =~ /^file \S+ written containing PID \d+$/;
    return 1 if $msg =~ /^smartd has fork\(\)ed into background mode\. New PID=\d+\.$/;
    return 1 if $msg =~ /^smartd version \S+ Copyright /;

    if ( $msg =~ /^Device: (\S+), SMART Prefailure Attribute: (\d+) (\S+) changed from (\d+) to (\d+)$/ ) {
	return 1 if ($4 > 200) && ($5 > 200);
    }

    return 0;
}

sub skipidentd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Connection from \S+$/;
    return 1 if $msg =~ /^from: (\d|\.)+ \( \S+ \) for: \d+, \d+$/;
    return 1 if $msg =~ /^Returned: \d+ , \d+ : NO-USER$/;

    return 0;
}

sub skipinetd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /Child Status Changed/;
    return 1 if $msg =~ /accept: Protocol error/;
    return 1 if $msg =~ /^connection from \S+, service (dictid|ftp|imaps?|nntps?|pop3s?|smtps?) /;
    return 1 if $msg =~ /^warning: can't verify hostname/;
    return 1 if $msg =~ /^warning: host name\/(address|name) mismatch/;

    if ( $msg =~ /^connection from (\S+), service (webster) / ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    return 0;
}

sub skiprdist
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^\S+: startup for \S+$/;
    return 1 if $msg =~ /^\S+: LOCAL ERROR: Response time out$/;
    return 1 if $msg =~ /^\S+: LOCAL ERROR: Unexpected input from server: /;
    return 1 if $msg =~ /^\S+: \S+: REMOTE ERROR: shell returned \d+$/;

    return 0;
}

sub skipwebsterd
{
    my ( $msg ) = @_;

    if ( $msg =~ /^connect from (\S+)$/ ) {
	return 1 if $1 =~ /$LOCAL/oi;
    }

    return 0;
}

#
# Gets syslog: and syslogd: messages
#
sub skipsyslogd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^(exiting|going down) on signal 15/;
    return 1 if $msg =~ /no \/var\/yp\/securenets file/;
    return 1 if $msg =~ /^restart$/;
    return 1 if $msg =~ /^Exiting on signal 15$/;

    return 0;
}

sub skipnntpd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ / cpstdin: EOF before period /;
    return 1 if $msg =~ /Broken pipe$/;
    return 1 if $msg =~ /Connection reset by peer$/;
    return 1 if $msg =~ /transfer_timeout$/;

    return 0;
}

sub skipftpd
{
    my ( $msg ) = @_;
    local ( $host );

    return 1 if $msg =~ /^connection from \S+ to \S+$/;
    return 1 if $msg =~ /^ANONYMOUS FTP LOGIN FROM /;
    return 1 if $msg =~ /^FTP session closed$/;
    return 1 if $msg =~ /^(Data|Total) traffic: \d+ bytes? in \d+ (file|transfer)s?$/;
    return 1 if $msg =~ /^User ftp timed out after \d+ seconds/;
    return 1 if $msg =~ /^User unknown timed out after \d+ seconds/;
    return 1 if $msg =~ /anonymous password not rfc822/;
    return 1 if $msg =~ /^lost connection to /;
    return 1 if $msg =~ /getpeername [()a-z]+: Socket is not connected$/;
    return 1 if $msg =~ /getsockname [()a-z]+: Invalid argument$/;
    return 1 if $msg =~ /^refused PORT $PRIVIP from /o;

    if ( $msg =~ /^refused PORT \S+ from (\S+)$/ ) {
	$host = parsehost($1);
	$FTP{'refused PORT: '.$host."\n"}++;
	return 1;
    }

    if ( $msg =~ /^FTP LOGIN FAILED FROM (\S+), / ) {
	$host = parsehost($1);
	$FTP{"LOGIN FAILED: from $host\n"}++;
	return 1;
    }

    return 0;
}

sub skipproftpd
{
    my ( $msg ) = @_;
    local ( $host );
    local ( $tmp );

    return 1 if $msg =~ / - (ANON|USER) \S+: Login successful.$/;
    return 1 if $msg =~ / - Preparing to chroot to directory /;
    return 1 if $msg =~ / - FTP session (opened|closed).$/;
    return 1 if $msg =~ / - FTP session idle timeout, disconnected.$/;
    return 1 if $msg =~ / - Data transfer stall timeout: \d+ seconds$/;
    return 1 if $msg =~ / - (FTP login|Session) timed out, disconnected$/;
    return 1 if $msg =~ / - Refused PORT $PRIVIP /o;
    return 1 if $msg =~ / - Refused EPRT \|\d\|$PRIVIP|\d+\| /o;
    return 1 if $msg =~ / - ProFTPD killed \(signal 15\)$/;
    return 1 if $msg =~ / - ProFTPD \S+ standalone mode SHUTDOWN$/;
    return 1 if $msg =~ / - ProFTPD \S+ \S+ \(.+\) standalone mode STARTUP$/;
    return 1 if $msg =~ / - notice: user \S+: aborting transfer: (Broken pipe|Data connection closed\.)$/;

    if ( $msg =~ /^\S+ \((\S+)\) - Refused (XPRT|PORT) \S+ / ) {
	$host = parsehost($1);
	$FTP{'refused PORT: from '.$host."\n"}++;
	return 1;
    }

    # these get dual-logged
    return 1 if $msg =~ / - no such user /;
    if ( $msg =~ /^\S+ \((\S+)\) - USER \S+: no such user found from / ) {
	$host = parsehost($1);
	$FTP{"LOGIN FAILED: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+ \((\S+)\) - USER (\S+) \(Login failed\): / ) {
	$host = parsehost($1);
	$FTP{"LOGIN FAILED: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+ \((\S+)\) - (Maximum login attempts) \(\d+\) (exceeded)($|,)/ ) {
	$host = parsehost($1);
	$tmp = "$2 $3";
	$FTP{"$tmp: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+ \((\S+)\) - SECURITY VIOLATION: (.+)$/ ) {
	$host = parsehost($1);
	$tmp = $2;
	$FTP{"SECURITY VIOLATION: from $host: $tmp\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+ \((\S+)\) - FTP no transfer timeout, disconnected$/ ) {
	$host = parsehost($1);
	$FTP{"NO TRANSFER TIMEOUT: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ /^\S+ \((\S+)\) - Connection refused \((.+)\)/ ) {
	$host = parsehost($1);
	$tmp = $2;
	$FTP{"$tmp: from $host\n"}++;
	return 1;
    }

    if ( $msg =~ / - (getnameinfo) error: (.+)$/ ) {
	$FTP{"$1 error: $2\n"}++;
	return 1;
    }

    return 0;
}

sub skipamd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^\S+ (mounted|referenced|restarted) fstype \S+ on \S+$/;
    return 1 if $msg =~ /^\S+ unmounted fstype \S+ from \S+$/;
    return 1 if $msg =~ /^Flushed \S+ dependent on \S+$/;
    return 1 if $msg =~ /^\S+ mount: No such file or directory$/;
    return 1 if $msg =~ /^extra mkdirs required for /;
    return 1 if $msg =~ /^restarting \S+ on \S+$/;
    return 1 if $msg =~ /^get_nfs_version: returning \S+ on host \S+$/;
    return 1 if $msg =~ /^file server \S+ type \S+ starts up$/;
    return 1 if $msg =~ /^\S+ (MOUNT|NFS) version:? \d(,|$)/;
    return 1 if $msg =~ /^\S+ using NFS transport \S+$/;
    return 1 if $msg =~ /^\S+ is on a remote network$/;
    return 1 if $msg =~ /^Using remopts=/;
    return 1 if $msg =~ /^amq says flush cache$/;
    return 1 if $msg =~ /^failed to create RPC client to /;
    return 1 if $msg =~ /^\S+: disabling nfs congestion window$/;
    return 1 if $msg =~ /^AM-UTILS VERSION /i;
    return 1 if $msg =~ /^(Built by|Copyright|Map support for:|Network( \d+)?:) /;
    return 1 if $msg =~ /^(cpu|full_os)=/;
    return 1 if $msg =~ /^(\s*(AMFS|FS|auto|cdfs|direct|error|host|inherit|linkx?|mfs|nfs[3xl]?|nullfs|pcfs|program|toplvl|ufs|umapfs|union|unionfs)[.,:])+\s*$/;
    return 1 if $msg =~ /^My ip addr is /;
    return 1 if $msg =~ /^released controlling tty using /;
    return 1 if $msg =~ /^NIS domain name is not set\./;

    return 0;
}

sub skipcyrus
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^(duplicate|tls)_prune:( \S+:)? purged \d+ out of \d+ entries$/;
    return 1 if $msg =~ /^duplicate_prune: pruning back \d+ days$/;
    return 1 if $msg =~ /^(done )?(checkpointing|recovering) (cyrus databases|mboxlist)$/;
    return 1 if $msg =~ /^(done )?running mboxlist recovery$/;
    return 1 if $msg =~ /^expunged \d+ out of \d+ messages from \d+ mailboxes$/;

    # Cyrus 1.5.14 spells "elminated"
    return 1 if $msg =~ /^dupelim: eli?minated duplicate message to /;

    return 1 if $msg =~ /^(DBERROR db3|DBMSG): \d+ lockers$/;

    return 0;
}

sub skipvtund
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^Connecting to \S+$/;
    return 1 if $msg =~ /^Connect to \S+ failed. Connection timed out\(\d+\)$/;
    return 1 if $msg =~ /^\S+ encryption initialized$/;

    return 0;
}

sub skippptpd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^MGR: Manager process started$/;

    return 0;
}

sub skipstunnel
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^stunnel \S+ on \S+/;
    return 1 if $msg =~ /^\S+ connected from [0-9.:]+$/;
    return 1 if $msg =~ /^Connection closed: \d+ bytes sent to SSL, \d+ bytes sent to socket$/;
    return 1 if $msg =~ /^SSL_accept: error:0+::/;
    return 1 if $msg =~ /^SSL_accept: error(:[^:]+)+:(no shared cipher|unknown protocol)$/;

    return 0;
}

sub skipracoon
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^INFO: pfkey.c:\d+: IPsec-SA (deleted|established|expired): (AH|ESP)\/Transport /;
    return 1 if $msg =~ /^INFO: isakmp.c:\d+: ISAKMP-SA (deleted|established|expired) /;
    return 1 if $msg =~ /^INFO: isakmp.c:\d+: IPsec-SA request for \S+ queued due to no phase1 found.$/;
    return 1 if $msg =~ /^INFO: isakmp.c:\d+: begin (Aggressive|Identity Protection) mode.$/;
    return 1 if $msg =~ /^INFO: isakmp.c:\d+: (initiate|respond) new phase \d+ negotiation: /;
    return 1 if $msg =~ /^INFO: isakmp_inf.c:\d+: purged (IPsec|ISAKMP)-SA proto_id=(AH|ESP|ISAKMP)/;
    return 1 if $msg =~ /^INFO: vendorid.c:\d+: received Vendor ID: /;
    return 1 if $msg =~ /^NOTIFY: oakley.c:\d+: couldn't find the proper pskey, try to get one by the peer's address.$/;
    return 1 if $msg =~ /^WARNING: ipsec_doi.c:\d+: attribute has been modified.$/;
    return 1 if $msg =~ /^WARNING: isakmp_inf.c:\d+: ignore RESPONDER-LIFETIME notification.$/;
    return 1 if $msg =~ /^ERROR: ipsec_doi.c:\d+: Only a single transform payload is allowed during phase 1 processing.$/;
    return 1 if $msg =~ /^ERROR: isakmp_inf.c:\d+: ignore information due to hash mismatch$/;

    return 0;
}

sub skiprsnapshot
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /: completed successfully$/;

    return 0;
}

sub skiprsynconly
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^OK: /;

    return 0;
}

sub skipjabberd
{
    my ( $msg ) = @_;

    return 1 if $msg =~ /^(\[\d+\] )?\[\S+, port=\d+\] (dis)?connect$/;
    return 1 if $msg =~ /^(\[\d+\] )?(bound|requesting session): jid=/;
    return 1 if $msg =~ /^(\[\d+\] )?SASL authentication succeeded: mechanism=\S+; authzid=/;
    return 1 if $msg =~ /^(\[\d+\] )?\[\S+, port=\d+\] write error: Broken pipe \(\d+\)$/;
    return 1 if $msg =~ /^\S+ resolved to \S+ \(\d+ seconds? to live\)$/;
    return 1 if $msg =~ /^(incom|outgo)ing route \S+ is now valid; (destination|source)=\S+, port \d+$/;
    return 1 if $msg =~ /^session (start|end|replac)ed: jid=/;
    return 1 if $msg =~ /^ready for (connections|sessions)$/;
    return 1 if $msg =~ /^ready to (resolve)$/;
    return 1 if $msg =~ /^\[\S+, port=\d+\] listening for( \S+)? connections$/;
    return 1 if $msg =~ /^\[\S+, port=\d+\] authenticated as /;
    return 1 if $msg =~ /^attempting connection to router at \S+, port=\d+$/;
    return 1 if $msg =~ /^attempting reconnect \(\d+ left\)$/;
    return 1 if $msg =~ /^connection to router (closed|established)$/;
    return 1 if $msg =~ /^connection attempt to router failed: /;
    return 1 if $msg =~ /^starting up$/;
    return 1 if $msg =~ /^shutting down$/;
    return 1 if $msg =~ /^reopening log \.\.\.$/;
    return 1 if $msg =~ /^log started$/;
    return 1 if $msg =~ /^process id is \d+, written to /;
    return 1 if $msg =~ /^\S+ online \(bound to \S+, port \d+\)$/;
    return 1 if $msg =~ /^\S+ set as default route$/;
    return 1 if $msg =~ /^\S+ default route offline$/;
    return 1 if $msg =~ /^\S+ configured; realm=/;
    return 1 if $msg =~ /^\S+ offline$/;
    return 1 if $msg =~ /^initialised auth module /;
    return 1 if $msg =~ /^initialised storage driver /;
    return 1 if $msg =~ /^loaded user table \(\d+ users?\)$/;
    return 1 if $msg =~ /^version: /;

    return 0;
}

sub skipnetgeardhcp
{
    return 1 if $msg =~ /^Send from port 0$/;

    return 0;
}

sub skipnetgeartelstra
{
    return 1 if $msg =~ /^Receive_heartbeats Status = 235$/;
    return 1 if $msg =~ /^Drop HeartBeat_request$/;

    return 0;
}

sub skipnetgearpacket
{
    my ( $msg ) = @_;

    if ( $msg =~ /^PROTO_(\S+), SIP:(\S+): \d+, DIP:(\S+): (\d+),/ ) {
	$BLOCKED{sprintf("%-10s %-15s %-15s\n", $1.'('.$4.')', $3, $2)}++;
	return 1;
    }

    if ( $msg =~ /^(\S+\(\d+(,\d+)?\))\s+Dest IP\s*:\s*(\S+),\s+Src IP\s*:\s*(\S+)/ ) {
	$BLOCKED{sprintf("%-10s %-15s %-15s\n", $1, $3, $4)}++;
	return 1;
    }

    return 0;
}

sub skipsipura
{
    return 1 if $msg =~ / -- (Requesting|Successful) resync /;

    return 0;
}
