check if client allready have ip address and if it does
authorDobrica Pavlinusic <dpavlin@rot13.org>
Mon, 17 Aug 2009 13:27:18 +0000 (13:27 +0000)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Mon, 17 Aug 2009 13:27:18 +0000 (13:27 +0000)
don't respond to it unless it's in our ip range, but
record information for later review

lib/PXElator/client.pm
lib/PXElator/dhcpd.pm
lib/PXElator/t/dhcpd.t

index 8950cb1..feda6a4 100644 (file)
@@ -6,7 +6,6 @@ use autodie;
 
 use File::Slurp;
 use Net::Ping;
-use Carp qw/confess/;
 
 use server;
 use format;
@@ -31,7 +30,7 @@ sub conf_value {
        } elsif ( -f $path ) {
                $value = read_file $path;
        } else {
-               confess "$path not file or symlink";
+               warn "W: $path not file or symlink\n";
        }
        return $value;
 }
@@ -85,15 +84,20 @@ sub next_ip($) {
 
        warn "next_ip $ip\n";
 
+       save_ip_mac( $ip, $mac );
+
+       return $ip;
+}
+
+sub save_ip_mac {
+       my ($ip,$mac) = @_;
+
        mkdir ip_path($ip);
 
        my $mac_path = mac_path($mac);
        unlink $mac_path if -e $mac_path;       # XXX audit?
        symlink ip_path($ip), $mac_path;
        write_file ip_path($ip,'mac'), $mac;
-
-       return $ip;
-
 }
 
 sub ip_from_mac($) {
index a1bc5de..809913a 100644 (file)
@@ -39,8 +39,8 @@ warn "server ip $server::ip range: $server::ip_from - $server::ip_to\n";
 
 use client;
 
-sub client_ip {
-       my ( $mac ) = @_;
+sub client_mac_ip {
+       my ( $mac, $request_ip ) = @_;
 
        my $conf = $server::conf;
        mkdir $conf unless -e $conf;
@@ -50,9 +50,13 @@ sub client_ip {
        if ( $ip = client::ip_from_mac( $mac ) ) {
                print "RENEW $mac $ip\n";
                return $ip;
-       } else {
+       } elsif ( in_our_range( $request_ip ) ) {
                $ip = client::next_ip( $mac );
                print "NEW $mac $ip\n";
+       } else {
+               $ip = $request_ip;
+               client::save_ip_mac( $ip, $mac );
+               warn "W: $ip our of server range $server::ip $server::netmask\n";
        }
 
        return $ip;
@@ -66,6 +70,17 @@ use client;
 our $file;
 our $transaction = 0; # FIXME predictible transaction numbers
 
+sub ip2bin { pack('C*', split(/\./, $_[0])) };
+sub in_our_range {
+       my $ip = shift;
+       return 1 if $ip eq '0.0.0.0';
+       return 1 if (
+               ( ip2bin($ip)         & ip2bin($server::netmask) )
+               eq
+               ( ip2bin($server::ip) & ip2bin($server::netmask) )
+       );
+}
+
 sub process_packet {
        my $sock = shift;
 
@@ -85,7 +100,7 @@ sub process_packet {
        warn "recv: ", $dhcp->toString if $debug;
 
        my $mac = substr($dhcp->chaddr(),0,$dhcp->hlen()*2);
-       my $ip = client_ip($mac);
+       my $ip = client_mac_ip($mac, $dhcp->ciaddr);
 
        my $hostname = $dhcp->getOptionValue(DHO_HOST_NAME);
        print "$ip ", client::conf( $ip => 'hostname', default => $hostname ), " >> /etc/hosts\n";
@@ -186,20 +201,25 @@ sub process_packet {
        $packet = new Net::DHCP::Packet( %$packet );
        warn "send ",$packet->toString() if $debug;
 
-       CouchDB::audit( $audit->{type}, $audit );
+       if ( in_our_range( $ip ) ) {
+               my $buff = $packet->serialize();
 
-       my $reply = IO::Socket::INET->new(
-               LocalAddr => $server::ip,
-               LocalPort => 67,
-               Proto => "udp",
-               Broadcast => 1,
-               PeerAddr => '255.255.255.255',
-               PeerPort => 68,
-               Reuse => 1,
-       ) or die "socket: $@";
-
-       my $buff = $packet->serialize();
-       $reply->send( $buff, 0 ) or die "Error sending: $!\n";
+               my $reply = IO::Socket::INET->new(
+                       LocalAddr => $server::ip,
+                       LocalPort => 67,
+                       Proto => "udp",
+                       Broadcast => 1,
+                       PeerAddr => '255.255.255.255',
+                       PeerPort => 68,
+                       Reuse => 1,
+               ) or die "socket: $@";
+
+               $reply->send( $buff, 0 ) or die "Error sending: $!\n";
+       } else {
+               $audit->{error} = "$ip our of our range $server::ip $server::netmask";
+       }
+
+       CouchDB::audit( $audit->{type}, $audit );
 
 #      system("arp -s $ip $mac"),
 
index f769009..dabb953 100755 (executable)
@@ -4,8 +4,11 @@ use warnings;
 use strict;
 use autodie;
 
-use Test::More tests => 2;
+use Test::More tests => 6;
 
 use_ok 'dhcpd';
 
 ok( ! $dhcpd::transaction, 'transaction' );
+
+ok( dhcpd::in_our_range($_), "in_our_range $_" ) foreach ( qw/0.0.0.0 172.16.10.1/ );
+ok( ! dhcpd::in_our_range($_), "! in_our_range $_" ) foreach ( qw/10.60.0.42 161.53.120.3/ );