require './nets.pl';
require './survey.pl';
require './mbd.pm';
+use lib '../include';
+use nms;
+use strict;
+use warnings;
+
+my ($dbh, $q);
sub fhbits {
my $bits = 0;
open LOG, ">>", "mbd.log";
-my @ports = ( mbd::find_all_ports() , $Config::survey_port_low, $Config::survey_port_high );
+my @ports = ( mbd::find_all_ports() , $Config::survey_port_low .. $Config::survey_port_high );
# Open a socket for each port
my @socks = ();
for my $sport (keys %active_surveys) {
my $age = Time::HiRes::tv_interval($active_surveys{$sport}{start}, $now);
if ($age > $Config::survey_time && $active_surveys{$sport}{active}) {
- print "Survey for port " . $active_surveys{$sport}{dport} . ": " .
- $active_surveys{$sport}{num} . " active servers.\n";
+ print "Survey for '" . $Config::access_list[$active_surveys{$sport}{entry}]->{name} . "'/" .
+ $active_surveys{$sport}{dport} . ": " . $active_surveys{$sport}{num} . " active servers.\n";
$active_surveys{$sport}{active} = 0;
+
+ # (re)connect to the database if needed
+ if (!defined($dbh) || !$dbh->ping) {
+ $dbh = nms::db_connect();
+ $q = $dbh->prepare("INSERT INTO mbd_log (ts,game,port,description,active_servers) VALUES (CURRENT_TIMESTAMP,?,?,?,?)")
+ or die "Couldn't prepare query";
+ }
+ $q->execute($active_surveys{$sport}{entry}, $active_surveys{$sport}{dport}, $Config::access_list[$active_surveys{$sport}{entry}]->{name}, $active_surveys{$sport}{num});
}
if ($age > $Config::survey_time * 3.0) {
delete $active_surveys{$sport};
my ($sport, $saddr) = sockaddr_in($addr);
my ($dport, $daddr) = sockaddr_in(getsockname($sock));
my $size = length($data);
-
+
# Check if this is a survey reply
if ($dport >= $Config::survey_port_low && $dport <= $Config::survey_port_high) {
if (!exists($active_surveys{$dport})) {
next;
}
-
+
# Rate limiting
if (exists($last_sent{$saddr}{$dport})) {
my $elapsed = Time::HiRes::tv_interval($last_sent{$saddr}{$dport}, $now);
if ($elapsed < 1.0) {
print LOG "$dport $size 2\n";
print inet_ntoa($saddr), ", $dport, $size bytes => rate-limited ($elapsed secs since last)\n";
+ next;
}
- next;
}
-
+
# We don't get the packet's destination address, but I guess this should do...
# Check against the ACL.
my $pass = 0;
+ my $entry = -1;
for my $rule (@Config::access_list) {
+ ++$entry;
+
next unless (mbd::match_ranges($dport, $rule->{'ports'}));
next unless (mbd::match_ranges($size, $rule->{'sizes'}));
# The packet is OK! Do we already have a recent enough survey
# for this port, or should we use this packet?
my $survey = 1;
- if (exists($last_survey{$dport})) {
- my $age = Time::HiRes::tv_interval($last_survey{$dport}, $now);
+ if (exists($last_survey{$entry . "/" . $dport})) {
+ my $age = Time::HiRes::tv_interval($last_survey{$entry . "/" . $dport}, $now);
if ($age < $Config::survey_freq) {
$survey = 0;
}
# New survey; find an unused port
my $survey_sport;
- for my $port ($Config::survey_port_low..$Config::survey_port_high) {
- if (!exists($active_surveys{$port})) {
- $survey_sport = $port;
-
- $active_surveys{$port} = {
- start => $now,
- active => 1,
- dport => $dport,
- num => 0
- };
- $last_survey{$dport} = $now;
-
- last;
+ if ($survey) {
+ for my $port ($Config::survey_port_low..$Config::survey_port_high) {
+ if (!exists($active_surveys{$port})) {
+ $survey_sport = $port;
+
+ $active_surveys{$port} = {
+ start => $now,
+ active => 1,
+ dport => $dport,
+ entry => $entry,
+ num => 0
+ };
+ $last_survey{$entry . "/" . $dport} = $now;
+
+ last;
+ }
}
- }
- if (!defined($survey_sport)) {
- print "WARNING: no free survey source ports, not surveying.\n";
- $survey = 0;
+ if (!defined($survey_sport)) {
+ print "WARNING: no free survey source ports, not surveying.\n";
+ $survey = 0;
+ }
}
my $num_nets = 0;
for my $net (@Config::networks) {
- next if (cache_cidrlookup(inet_ntoa($saddr), $net));
-
my ($range) = cache_cidrrange($net);
$range =~ /-(.*?)$/;
my $broadcast = $1;
- $sendsock->set({
- ip => {
- saddr => inet_ntoa($saddr),
- daddr => $broadcast
- },
- udp => {
- source => $sport,
- dest => $dport,
- data => $data
- }
- });
- $sendsock->send;
-
if ($survey) {
$sendsock->set({
ip => {
$sendsock->send;
}
+ next if (cache_cidrlookup(inet_ntoa($saddr), $net));
+
+ $sendsock->set({
+ ip => {
+ saddr => inet_ntoa($saddr),
+ daddr => $broadcast
+ },
+ udp => {
+ source => $sport,
+ dest => $dport,
+ data => $data
+ }
+ });
+ $sendsock->send;
+
++$num_nets;
}