use File::Slurp;
use Net::Ping;
-use Carp qw/confess/;
use server;
use format;
} elsif ( -f $path ) {
$value = read_file $path;
} else {
- confess "$path not file or symlink";
+ warn "W: $path not file or symlink\n";
}
return $value;
}
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($) {
use client;
-sub client_ip {
- my ( $mac ) = @_;
+sub client_mac_ip {
+ my ( $mac, $request_ip ) = @_;
my $conf = $server::conf;
mkdir $conf unless -e $conf;
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;
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;
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";
$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"),