From 39d8dc5a852ab213302568b6556d73cdbab654c3 Mon Sep 17 00:00:00 2001 From: Dobrica Pavlinusic Date: Mon, 17 Aug 2009 13:27:18 +0000 Subject: [PATCH] check if client allready have ip address and if it does don't respond to it unless it's in our ip range, but record information for later review --- lib/PXElator/client.pm | 14 +++++++---- lib/PXElator/dhcpd.pm | 54 +++++++++++++++++++++++++++++------------- lib/PXElator/t/dhcpd.t | 5 +++- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/lib/PXElator/client.pm b/lib/PXElator/client.pm index 8950cb1..feda6a4 100644 --- a/lib/PXElator/client.pm +++ b/lib/PXElator/client.pm @@ -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($) { diff --git a/lib/PXElator/dhcpd.pm b/lib/PXElator/dhcpd.pm index a1bc5de..809913a 100644 --- a/lib/PXElator/dhcpd.pm +++ b/lib/PXElator/dhcpd.pm @@ -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"), diff --git a/lib/PXElator/t/dhcpd.t b/lib/PXElator/t/dhcpd.t index f769009..dabb953 100755 --- a/lib/PXElator/t/dhcpd.t +++ b/lib/PXElator/t/dhcpd.t @@ -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/ ); -- 2.20.1