]> git.sesse.net Git - nms/commitdiff
Merge. master
authorroot <root@space>
Sat, 7 Apr 2007 16:30:09 +0000 (18:30 +0200)
committerroot <root@space>
Sat, 7 Apr 2007 16:30:09 +0000 (18:30 +0200)
.bzrignore
clients/dhcpv6gen.pl [new file with mode: 0644]
config/make-named-secondary.pl
config/make-named.pl
config/make-port-config.pl
make-all-config.sh
mbd/access_list.pl
mbd/mbd.pl
mbd/survey.pl [new file with mode: 0644]
static-switches.txt
web/make-switches.pl

index 5f71d77ed8d23ce147904927a0d5f99925003a42..77ff49dd5e87d4d2492d464a966ff1ca3b628dee 100644 (file)
@@ -4,3 +4,6 @@ patchlist.txt
 switches.txt
 planning/planning
 mbd/nets.pl
+switches.sql
+include/config.local.pm
+mbd/mbd.log
diff --git a/clients/dhcpv6gen.pl b/clients/dhcpv6gen.pl
new file mode 100644 (file)
index 0000000..83db735
--- /dev/null
@@ -0,0 +1,30 @@
+open PATCHLIST, "/root/nms/switches.txt"
+       or die "switches.txt: $!";
+my %vlans = ();
+
+while (<PATCHLIST>) {
+       if (/87\.76\.(\d+)\.(\d+) 26 e(\d+)-(\d+)/) {
+               my $vlannum = $3.$4;
+               my $helper = "87.76.$1." . ($2+1);
+               my $name = "e$3-$4";
+               my $z = sprintf "f%03u", $vlannum;
+               $z =~ /(.)(.)(.)(.)/; $vlans{$helper} = [ $vlannum, $name, "$4.$3.$2.$1" ];
+       }
+}
+
+while (<>) {
+       /DHCPOFFER on 87.76.\d+.\d+ to 00:(.)(.):(.)(.):(.)(.):(.)(.):(.)(.) \((.*?)\) via (\d+\.\d+\.\d+\.\d+)/ or next;
+       my $v = $vlans{$12};
+       open NSUPDATE, "| nsupdate -y DHCP_UPDATER:F388UOhaIIKHRH9TDE5PTA==";
+       print NSUPDATE <<"EOF";
+server 127.0.0.1
+update delete $11.v6.$v->[1].tg07.gathering.org. AAAA
+update add $11.v6.$v->[1].tg07.gathering.org. 3600 AAAA 2001:16d8:ffff:f$v->[0]:02$1$2:$3$4ff:fe$5$6:$7$8$9$10
+send
+update delete $10.$9.$8.$7.$6.$5.e.f.f.f.$4.$3.$2.$1.2.0.$v->[2].f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa. PTR
+update add $10.$9.$8.$7.$6.$5.e.f.f.f.$4.$3.$2.$1.2.0.$v->[2].f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa. 3600 PTR $11.v6.$v->[1].tg07.gathering.org.
+send
+EOF
+       close NSUPDATE;
+}
+
index a9b3c12af32ae7ec91134c084290a97142b4a83d..4f4047f2b67c0dd8aa5418fc7b05c1219420bc1d 100755 (executable)
@@ -46,6 +46,23 @@ zone "tg07.gathering.org" {
        file "tg07.gathering.org";
 };
 
+// hijack
+zone "sth.ip-performance.se" {
+       type slave;
+       notify no;
+       masters { 87.76.254.2; };
+       file "sth.ip-performance.se";
+};
+
+// linknett
+zone "0.76.87.in-addr.arpa" {
+       type slave;
+       notify no;
+       masters { 87.76.254.2; };
+       file "0.76.87.in-addr.arpa";
+       allow-transfer { 193.0.0.0/22; };
+};
+
 // linknett
 zone "174.76.87.in-addr.arpa" {
        type slave;
@@ -88,6 +105,15 @@ zone "76.87.in-addr.arpa" {
        file "dynamic/76.87.in-addr.arpa";      
        allow-transfer { 194.19.3.20; 193.0.0.0/22; };
 };
+zone "f.f.f.f.8.d.6.1.1.0.0.2.ip6.in-addr.arpa" {
+       type slave;
+       notify no;
+       masters { 87.76.254.2; };
+       allow-update { key DHCP_UPDATER; };
+       file "dynamic/f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa";        
+       allow-transfer { 194.19.3.20; };
+};
+
 
 key DHCP_UPDATER {
        algorithm HMAC-MD5.SIG-ALG.REG.INT;
index d2bbf02096abd201508c8770ba8a574f9bfdfb70..2fb295b472763890198b6c316b94b40c5db092ac 100755 (executable)
@@ -46,6 +46,22 @@ zone "tg07.gathering.org" {
        allow-transfer { 87.76.255.2; };
 };
 
+// hijack
+zone "sth.ip-performance.se" {
+       type master;
+       file "sth.ip-performance.se";
+       notify yes;
+       allow-transfer { 87.76.255.2; };
+};
+
+// linknett
+zone "0.76.87.in-addr.arpa" {
+       type master;
+       file "0.76.87.in-addr.arpa";
+       notify yes;
+       allow-transfer { 87.76.255.2; 193.0.0.0/22; };
+};
+
 // linknett
 zone "174.76.87.in-addr.arpa" {
        type master;
@@ -88,6 +104,13 @@ zone "76.87.in-addr.arpa" {
        file "dynamic/76.87.in-addr.arpa";      
        allow-transfer { 194.19.3.20; 87.76.255.2; 193.0.0.0/22; };
 };
+zone "f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa" {
+       type master;
+       allow-update { key DHCP_UPDATER; };
+       notify yes;
+       file "dynamic/f.f.f.f.8.d.6.1.1.0.0.2.ip6.arpa";        
+       allow-transfer { 194.19.3.20; 87.76.255.2; };
+};
 
 EOF
 
index 893d4f406c1b6256a8cf71eaec007b70b4ac99d4..6b3ba3319143df16aff25fa37809cf3a580bae5a 100755 (executable)
@@ -1,7 +1,8 @@
 #! /usr/bin/perl
 open PATCHLIST, "<patchlist.txt"
        or die "patchlist.txt: $!";
-my %distros = ();
+my %vlans = ();
+my %ports = ();
 
 while (<PATCHLIST>) {
        chomp;
@@ -28,24 +29,27 @@ while (<PATCHLIST>) {
        my $vlan = "$row$switch";
        my $ipv6 = sprintf "F%02u%u", $row, $switch;
 
-       $distros{$distro} .= <<"EOF";
+       $vlans{$distro} .= <<"EOF";
 vlan $vlan
   name $name
 !
+EOF
+       $ports{$distro} .= <<"EOF";
 default interface vlan $vlan
 interface vlan $vlan
   description $name
   ip address $ip 255.255.255.192
-  ip directed-broadcast 10
+  ip directed-broadcast 101
   ip helper-address 87.76.254.2
   no ip proxy-arp
   ip access-group great-wall-of-tg in
   ipv6 address 2001:16D8:FFFF:${ipv6}::1/64
-  ip igmp version 3
+  ip igmp version 2
   ip pim sparse-mode
   no shutdown
+  exit
 !
 default interface $port
 interface $port
  description $name
@@ -57,14 +61,20 @@ interface $port
 
  storm-control broadcast level 2
  no shutdown
+ exit
 !
 EOF
 }
 
-for my $distro (keys %distros) {
+for my $distro (keys %vlans) {
        open DISTRO, ">$distro-config"
                or die "$distro-config: $!";
-       print DISTRO $distros{$distro};
+       print DISTRO <<"EOF";
+access-list 101 remark ip directed broadcast
+access-list 101 permit ip any any dscp cs7
+EOF
+       print DISTRO $vlans{$distro};
+       print DISTRO $ports{$distro};
        print DISTRO "end\n";
        close DISTRO;
 }
index 276a4d41b88c3d39e50827934b429f670617bd16..1db0af253c8434f31f10bdbbff59a25cdfe3b4af 100755 (executable)
@@ -11,7 +11,7 @@ cat static-switches.txt >> switches.txt
 scp mbd-ports *-config sesse@f1:/tftpboot/portcfg/
 
 # regenerate the mbd netlist
-(echo '# Autogenerated. Do not touch!' ; echo "package Config;"; echo 'our @networks = (' ; cut -d" " -f1-2 switches.txt | perl -e 'while (<>) { chomp; my ($net,$mask) = split / /; print "\t\"$net/$mask\",\n"; }' ; echo ');' ; echo '1;')  > mbd/nets.pl 
+(echo '# Autogenerated. Do not touch!' ; echo "package Config;"; echo 'our @networks = (' ; cut -d" " -f1-2 switches.txt | grep -vE '87\.76\.(130|131|216)\.0' | perl -e 'while (<>) { chomp; my ($net,$mask) = split / /; print "\t\"$net/$mask\",\n"; }' ; echo ');' ; echo '1;')  > mbd/nets.pl 
 
 perl web/make-switches.pl > switches.sql
 scp switches.sql root@space:
index 137f173e05445b40f5b5842c4813a0c68d3d7cd7..57ae61466172c5ba891d5fae035a11e354f59111 100644 (file)
@@ -4,6 +4,7 @@ package Config;
 our @access_list = (
        # half-life - untested (packet dump only)
        {
+               name => 'Half-Life',
                ports => [ 27015 ],
                sizes => [ 16 ]
        },
@@ -11,18 +12,21 @@ our @access_list = (
        # cs 1.6 - verified
        # (funker muligens for _alle_ source-spill inkl. hl2/cs:s)
        {
+               name => 'CS 1.6, other Source games',
                ports => [ 4242, "26900..26905", "27015..27020" ],
                sizes => [ 25 ]
        },
 
        # doom 3 - verified
        {
+               name => 'Doom 3',
                ports => [ "27666..27673" ],
                sizes => [ 14 ]
        },
 
        # quake 1 - verified
        {
+               name => 'Quake 1',
                ports => [ 26000 ],
                sizes => [ 12 ]
        },
@@ -30,6 +34,7 @@ our @access_list = (
        # q3a - tested with demo only
        # rtcw: enemy territory - untested (packet dump only)
        {
+               name => 'Quake 3 Arena, RTCW: ET',
                ports => [ "27960..27969" ],
                sizes => [ 15 ]
        },
@@ -37,30 +42,35 @@ our @access_list = (
        # bf2 - tested with demo only
        # bf2142 reportedly uses same engine
        {
+               name => 'BF2/BF2142',
                ports => [ "29900..29950" ],
                sizes => [ 8 ]
        },
 
        # bf1942 - unverified (packet dump only)
        {
+               name => 'BF1942',
                ports => [ "22000..22010" ],
                sizes => [ 8 ]
        },
        
        # quake 4 - tested with demo only, MUST select "internet"
        {
+               name => 'Quake 4',
                ports => [ 27950, 28004 ],
                sizes => [ 14 ]
        },
 
        # quake 2 - untested (packet dump only)
        {
+               name => 'Quake 2',
                ports => [ 27910 ],
                sizes => [ 11 ]
        },
 
        # warcraft 3 - untested (packet dump only)
        {
+               name => 'Warcraft 3',
                ports => [ "6112..6119" ],
                sizes => [ 16, 48 ],
                filter => sub { return (ord(substr(shift, 1, 1)) == 0x2f); }
@@ -68,30 +78,35 @@ our @access_list = (
 
        # ut2003/ut2004 - untested (packet dump only)
        {
+               name => 'UT2003/UT2004',
                ports => [ 10777 ],
                sizes => [ 5 ]
        },
 
        # soldat - untested (packet dump only)
        {
+               name => 'Soldat',
                ports => [ 23073 ],
                sizes => [ 8 ]
        },
 
        # starcraft - untested (packet dump only)
        {
+               name => 'Starcraft',
                ports => [ 6111, 6112 ],
                sizes => [ 8, 20 ]
        },
 
        # trackmania nations - untested (packet dump only)
        {
+               name => 'Trackmania Nations',
                ports => [ "2350..2370" ],
                sizes => [ 42 ]
        },
 
        # company of heroes - untested (packet dump only)
        {
+               name => 'Company of Heroes',
                ports => [ 9100 ],
                sizes => [ 39 ]
        },
@@ -99,8 +114,17 @@ our @access_list = (
        # command & conquer 3 - untested (packet dump only, reported to have some kind
        # of chat functionality)
        {
+               name => 'Command & Conquer 3',
                ports => [ "8086..8093" ],
-               sizes => [ 476 ]
+               sizes => [ 476 ],
+               filter => sub { return 0; }
+       },
+
+       # openttd
+       {
+               name => 'OpenTTD',
+               ports => [ 3979 ],
+               sizes => [ 3 ]
        },
 
        # unreal tournament, port 9777?
index 7fcc8d8100a3a67e6e2f41bd763d797c684e4a06..4900c1b21498a4a6f32e399f3fee2cab1daaf58f 100644 (file)
@@ -4,9 +4,17 @@ use warnings;
 use Socket;
 use Net::CIDR;
 use Net::RawIP;
+use Time::HiRes;
 require './access_list.pl';
 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;
@@ -16,9 +24,38 @@ sub fhbits {
        return $bits;
 }
 
+# used for rate limiting
+my %last_sent = ();
+
+# for own surveying
+my %active_surveys = ();
+my %last_survey = ();
+
+my %cidrcache = ();
+sub cache_cidrlookup {
+       my ($addr, $net) = @_;
+       my $key = $addr . " " . $net;
+
+       if (!exists($cidrcache{$key})) {
+               $cidrcache{$key} = Net::CIDR::cidrlookup($addr, $net);
+       }
+       return $cidrcache{$key};
+}
+
+my %rangecache = ();
+sub cache_cidrrange {
+       my ($net) = @_;
+
+       if (!exists($rangecache{$net})) {
+               ($rangecache{$net}) = Net::CIDR::cidr2range($net);
+       }
+
+       return $rangecache{$net};
+}
+
 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 = ();
@@ -40,6 +77,29 @@ 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 '" . $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};
+               }
+       }
+
        for my $sock (@socks) {
                next unless (vec($rout, fileno($sock), 1) == 1);
 
@@ -48,11 +108,40 @@ while (1) {
                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})) {
+                               print "WARNING: Unknown survey port $dport, ignoring\n";
+                               next;
+                       }
+                       if (!$active_surveys{$dport}{active}) {
+                               # remains
+                               next;
+                       }
+                       
+                       ++$active_surveys{$dport}{num};
 
+                       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;
+                       }
+               }
+               
                # 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'}));
 
@@ -67,19 +156,70 @@ while (1) {
                print LOG "$dport $size $pass\n";
 
                if (!$pass) {
-                       print "$dport, $size bytes => filtered\n";
+                       print inet_ntoa($saddr), ", $dport, $size bytes => filtered\n";
+                       next;
                }
 
-               next unless $pass;
+               $last_sent{$saddr}{$dport} = $now;
 
-               for my $net (@Config::networks) {
-                       next if (Net::CIDR::cidrlookup(inet_ntoa($saddr), $net));
+               # 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{$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;
+               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;
+                               }
+                       }
 
-                       my ($range) = Net::CIDR::cidr2range($net);
+                       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) {
+                       my ($range) = cache_cidrrange($net);
                        $range =~ /-(.*?)$/;
                        my $broadcast = $1;
 
-                       print inet_ntoa($saddr), ", $dport, $size bytes => $broadcast\n";
+                       if ($survey) {
+                               $sendsock->set({
+                                       ip => {
+                                               saddr => $Config::survey_ip,
+                                               daddr => $broadcast
+                                       },
+                                       udp => {
+                                               source => $survey_sport,
+                                               dest => $dport,
+                                               data => $data
+                                       }
+                               });
+                               $sendsock->send;
+                       }
+
+                       next if (cache_cidrlookup(inet_ntoa($saddr), $net));
 
                        $sendsock->set({
                                ip => {
@@ -93,6 +233,14 @@ while (1) {
                                }
                        });
                        $sendsock->send;
+
+                       ++$num_nets;
+               }
+
+               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..a948180
--- /dev/null
@@ -0,0 +1,10 @@
+package Config;
+
+our $survey_ip = "87.76.254.2";
+our $survey_port_low = 60100;
+our $survey_port_high = 60200;
+our $survey_freq = 60.0;
+our $survey_time = 10.0;
+
+1;
+
index 2619cd7007e5551953bee0f448446cfc2233cf90..d53a9b5fe8b3fb4e497774f1b3c2360b87638260 100644 (file)
@@ -11,7 +11,7 @@
 87.76.207.0 24 auditorium
 87.76.208.0 24 ute
 87.76.209.0 24 infodesk
-87.76.210.0 24 game-server
+87.76.211.0 24 qpad-scene
 87.76.212.0 24 game-client
 87.76.213.0 24 logistics
 87.76.215.0 24 security
@@ -19,5 +19,6 @@
 87.76.220.0 24 fugleberget
 87.76.222.0 24 democrew
 87.76.223.0 24 cam
+87.76.224.0 24 chillout
 87.76.250.0 24 noc
 87.76.252.0 24 presse
index e1d3fe9b3c4f400bfabc3a7e585317889723a2f6..9283546e2e0cf7023706f752305582c7af6de9e8 100644 (file)
@@ -11,9 +11,6 @@ print "SELECT pg_catalog.setval('polls_poll_seq', 1, false);\n";
 open PATCHLIST, "patchlist.txt"
        or die "patchlist.txt: $!";
 
-my $cc = 241;
-my $dd = 0;
-
 my $i = 1;
 while (<PATCHLIST>) {
        chomp;
@@ -46,24 +43,31 @@ while (<PATCHLIST>) {
        my $xx = $x + 12;
        my $yy = $y + (($s > 3) ? 50 : 48);
 
-       $dk = $dd + 7 + ($cc - 241) * 42;
-
-# lasses magic-factor =)
-       $dk += 4;
-       if ($dk > 13) {
-               $dk += 3;
-       }       
+       my ($ip, $range);
+       if ($s == 1) {
+               $ip = "87.76." . ($e) . ".2";
+               $range = "87.76." . ($e) . ".0";
+       } elsif ($s == 2) {
+               $ip = "87.76." . ($e) . ".66";
+               $range = "87.76." . ($e) . ".64";
+       } elsif ($s == 3) {
+               $ip = "87.76." . ($e) . ".130";
+               $range = "87.76." . ($e) . ".128";
+       } elsif ($s == 4) {
+               $ip = "87.76." . ($e + 1) . ".2";
+               $range = "87.76." . ($e + 1) . ".0";
+       } elsif ($s == 5) {
+               $ip = "87.76." . ($e + 1) . ".66";
+               $range = "87.76." . ($e + 1) . ".64";
+       } elsif ($s == 6) {
+               $ip = "87.76." . ($e + 1) . ".130";
+               $range = "87.76." . ($e + 1) . ".128";
+       }
 
-       print "insert into switches (ip, sysname, switchtype) values ('87.76.$cc.$dk', 'e$e-${s}sw', 'es3024');\n";
+       print "insert into switches (ip, sysname, switchtype) values ('$ip', 'e$e-${s}sw', 'es3024');\n";
        print "insert into placements (switch, placement) values ($i, box '(($x,$y),($xx,$yy))');\n";
        print "insert into dhcp (switch, network) values ($i, '87.76.$c.$d/26');\n";
        $i++;
-
-       $dd++;
-       if ($dd == 42) {
-               $cc++;
-               $dd = 0;
-       }
 }
 
 print "end;\n";