]> git.sesse.net Git - nms/commitdiff
Make survey functionality for MBD.
authorroot <root@sysrq>
Wed, 4 Apr 2007 12:32:57 +0000 (14:32 +0200)
committerroot <root@sysrq>
Wed, 4 Apr 2007 12:32:57 +0000 (14:32 +0200)
mbd/mbd.pl
mbd/survey.pl [new file with mode: 0644]

index dcc25fe242e8bd843a1741b0821c9f81c7f4978e..4843b0bb60cfea9a62388340e854749a8a3b3d4a 100644 (file)
@@ -7,6 +7,7 @@ use Net::RawIP;
 use Time::HiRes;
 require './access_list.pl';
 require './nets.pl';
+require './survey.pl';
 require './mbd.pm';
 
 sub fhbits {
@@ -20,6 +21,10 @@ sub fhbits {
 # used for rate limiting
 my %last_sent = ();
 
+# for own surveying
+my %active_surveys = ();
+my %last_survey = ();
+
 my %cidrcache = ();
 sub cache_cidrlookup {
        my ($addr, $net) = @_;
@@ -44,7 +49,7 @@ sub cache_cidrrange {
 
 open LOG, ">>", "mbd.log";
 
-my @ports = mbd::find_all_ports();
+my @ports = ( mbd::find_all_ports() , $Config::survey_port_low, $Config::survey_port_high );
 
 # Open a socket for each port
 my @socks = ();
@@ -66,6 +71,21 @@ while (1) {
        my $rout;
 
        my $nfound = select($rout=$rin, undef, undef, undef);
+       my $now = [Time::HiRes::gettimeofday];
+
+       # First of all, close any surveys that are due.
+       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";
+                       $active_surveys{$sport}{active} = 0;
+               }
+               if ($age > $Config::survey_time * 3.0) {
+                       delete $active_surveys{$sport};
+               }
+       }
+
        for my $sock (@socks) {
                next unless (vec($rout, fileno($sock), 1) == 1);
 
@@ -75,8 +95,23 @@ while (1) {
                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})) {
+                               print "WARNING: Unknown survey port $dport, ignoring\n";
+                               next;
+                       }
+                       if (!$active_surveys{$dport}{active}) {
+                               # remains
+                               next;
+                       }
+                       
+                       ++$active_surveys{$dport}{num};
+
+                       next;
+               }
+
                # Rate limiting
-               my $now = [Time::HiRes::gettimeofday];
                if (exists($last_sent{$saddr}{$dport})) {
                        my $elapsed = Time::HiRes::tv_interval($last_sent{$saddr}{$dport}, $now);
                        if ($elapsed < 1.0) {
@@ -110,8 +145,40 @@ while (1) {
 
                $last_sent{$saddr}{$dport} = $now;
 
-               my $num_nets = 0;
+               # 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 ($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 (!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));
 
@@ -131,9 +198,30 @@ while (1) {
                                }
                        });
                        $sendsock->send;
+
+                       if ($survey) {
+                               $sendsock->set({
+                                       ip => {
+                                               saddr => $Config::survey_ip,
+                                               daddr => $broadcast
+                                       },
+                                       udp => {
+                                               source => $survey_sport,
+                                               dest => $dport,
+                                               data => $data
+                                       }
+                               });
+                               $sendsock->send;
+                       }
+
                        ++$num_nets;
                }
-               print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks)\n";
+
+               if ($survey) {
+                       print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks) [+survey from port $survey_sport]\n";
+               } else {
+                       print inet_ntoa($saddr), ", $dport, $size bytes => ($num_nets networks)\n";
+               }
        }
 }
 
diff --git a/mbd/survey.pl b/mbd/survey.pl
new file mode 100644 (file)
index 0000000..b73a279
--- /dev/null
@@ -0,0 +1,10 @@
+package Config;
+
+our $survey_ip = "87.76.254.2";
+our $survey_port_low = 60000;
+our $survey_port_high = 60500;
+our $survey_freq = 60.0;
+our $survey_time = 3.0;
+
+1;
+