#!/usr/bin/perl
# smurf.saint
# 8/00, Sam Kline, WWDSI

$running_under_saint = 1;

require 'config/paths.pl';
require 'config/saint.cf';
require 'perl/misc.pl';
require 'perl/get_host.pl';
require 'perl/getfqdn.pl';
require 'perl/hostname.pl';
require 'perllib/getopts.pl';

print "BEGIN\n";
$usage = "Usage: smurf.saint [-v] [-m netmask] network\n";
if ($#ARGV < 0) {
   die $usage;
}

# check these netmasks by default
$netmask = "255.255.255.0,255.255.255.128,255.255.255.192";

$this_fqdn = &getfqdn(&hostname());
$this_host = $my_address ? $my_address : &get_host_addr($this_fqdn);

&Getopts("m:v") || die $usage;
$netmask = $opt_m if defined($opt_m);
die $usage unless defined $ARGV[0];
($network = $ARGV[0]) =~ s/\/.*$//; #remove trailing slash

die "Cannot find nmap" if (! -x $NMAP);

# Don't test our own broadcast addresses because they
# always result in false positives
$netmask =~ s/,/ /g;
%dont_scan = ();
if ($this_host ne "") {
  for (split /\s+/,$netmask) {
    @mask = split /\./;
    @net = split /\./, $this_host;
    @broadcast = @net;

    # get network and broadcast addresses
    $net[3] &= $mask[3] + 0;
    $net[2] &= $mask[2] + 0;
    $broadcast[3] |= $mask[3] ^ 255 + 0;
    $broadcast[2] |= $mask[2] ^ 255 + 0;
    $net_ip = join '.', @net;
    $broadcast_ip = join '.', @broadcast;
    $dont_scan{$net_ip} = 1;
    $dont_scan{$broadcast_ip} = 1;
  }
}

# Make list of broadcast addresses to test
%test_broadcasts = ();
for (split /\s+/,$netmask) {
    @mask = split /\./;
    @net = split /\./, $network;
    @broadcast = @net;

    # get network and broadcast addresses
    # (for safety, don't go beyond Class B)
    # (+0 used to cast to integer)
    $net[3] &= $mask[3] + 0;
    $net[2] &= $mask[2] + 0;
    $broadcast[3] |= $mask[3] ^ 255 + 0;
    $broadcast[2] |= $mask[2] ^ 255 + 0;

    $net_ip = join '.',@net;
    $net_C = join '.',@net[0..2];
    $broadcast_ip = join '.',@broadcast;
    $broadcast_C = join '.',@broadcast[0..2];

    if (!$dont_scan{$net_ip} &&
	$test_broadcasts{$net_C} !~ /\b$net[3],/) {
	    $test_broadcasts{$net_C} .= $net[3] . ",";
    }
    if (!$dont_scan{$broadcast_ip} &&
	$test_broadcasts{$broadcast_C} !~ /\b$broadcast[3],/) {
	    $test_broadcasts{$broadcast_C} .= $broadcast[3] . ",";
    }
}

$status = "n";
$service = basename ($0, '.saint');
$severity = "dos";
$trusted = "ANY\@ANY";
$trustee = "ANY\@ANY";
$service_output = "packet flooding problems";

for $test (keys %test_broadcasts) {
    ($arg = $test . "." . $test_broadcasts{$test}) =~ s/,$//;
    print "$arg\n" if $opt_v;
    open (CMD, "$NMAP -n -sP -PI \'$arg\' |");
    while(<CMD>) {
	if (/subnet broadcast address/ && /\(([\d\.]+)\)/) {
	    $target = $1;
	    $text = "broadcast address is a smurf amplifier";
	    &saint_print();
	}
    }
    close (CMD);
    open (CMD, "$NMAP -n -sU -p 1 \'$arg\' |");
    while(<CMD>) {
	if (/subnet broadcast address/ && /\(([\d\.]+)\)/) {
	    $target = $1;
	    $text = "broadcast address is a fraggle amplifier";
	    &saint_print();
	}
    }
    close (CMD);
}

