}
};
+my $cleanup_leases = sub {
+ my ($self, $last_run) = @_;
+ my ($current, $last, $lease, $dirty);
+
+ $self->{INTERVAL} = 5 if $self->{INTERVAL} <= 0;
+ $current = time;
+ $last = $last_run + ($self->{INTERVAL} * 60);
+
+ $self->$logger("Run 'cleanup_leases' $last < $current", INFO);
+
+ if ($last < $current) {
+ $last_run = $current;
+ my $leases = $self->{_leases};
+ $dirty = 0;
+ while ((my $lease, my $elems) = each (%$leases)) {
+ $self->$logger("Clean up lease: $lease\n". Dumper($elems));
+ if ($elems->{ends} < $last_run) {
+ $self->$logger("Considering $lease for clean up: $elems->{ends} < $last_run\n". Dumper($elems));
+ if ($elems->{'binding state'} eq 'active') {
+ $self->$logger("Setting $lease 'binding state' to free", INFO);
+ $elems->{'binding state'} = 'free';
+ $dirty = 1;
+ }
+ }
+ }
+ if ($dirty) {
+ my $res = $self->$write_lease_file();
+ if ($res) {
+ $self->$logger("Updated lease file", INFO);
+ }
+ }
+ }
+
+ return $last_run;
+};
+
#########################################################################
# Private methods which handle DHCP4 requests
#########################################################################
};
my $release_ip4 = sub {
- my ($self, $dhcpreq) = @_;
+ my ($self, $req) = @_;
my ($ip, $mac);
- $self->$logger($dhcpreq->toString());
- $ip = $dhcpreq->ciaddr();
- $mac = $self->$get_mac_ip4($dhcpreq);
+ $self->$logger($req->toString());
+ $ip = $req->ciaddr();
+ $mac = $self->$get_mac_ip4($req);
$self->$logger("Release request for IP: $ip MAC: $mac", INFO);
if ($self->{_leases}->{$ip}) {
my $lease = $self->{_leases}->{$ip};
if ($lease->{'hardware ethernet'} eq $mac) {
+ $self->$logger("Set binding state free IP: $ip MAC: $mac", INFO);
$lease->{'binding state'} = 'free';
+ $self->$write_lease_file();
}
- $self->$write_lease_file();
}
$self->$logger("Transaction:\n".Dumper($self->{_transaction}), INFO);
};
my ($self, $addr, $req) = @_;
$self->$logger("IPv6 request from [$addr]: $req", INFO);
- $self->{_sock_out_ip6} = IO::Socket::IP->new(
+ my $sock = IO::Socket::IP->new(
Domain => PF_INET6,
V6Only => 1,
Broadcast => 1,
die "[excuse_me_ip6] Socket creation error: $err\n";
};
$self->$logger("$addr: Not implemented here", INFO);
- $self->{_sock_out_ip6}->send("Not implemented here") || die "Error sending excuse: $!\n";
+ $sock->send("Not implemented here") || die "Error sending excuse: $!\n";
+ $sock->close;
};
#########################################################################
$self->{timeout} ||= 10;
$self->{lease_file} ||= '/tmp/dhcpd.leases';
$self->{conf_file} ||= '/tmp/dhcpd.cfg';
+ $self->{INTERVAL} ||= 5;
return $self;
}
$sel = IO::Select->new($self->{_sock_in_ip4});
$sel->add($self->{_sock_in_ip6});
+ my $last_run = time;
+
until ($time_to_die) {
my $buf = undef;
my $fromaddr;
eval { # catch fatal errors
while (@ready = $sel->can_read) {
$self->$logger("Waiting for incoming packet", INFO);
+ $last_run = $self->$cleanup_leases($last_run);
foreach $socket (@ready) {
if ($socket == $self->{_sock_in_ip4}) {
# receive ipv4 packet
- $fromaddr = $self->{_sock_in_ip4}->recv($buf, 4096)
+ $fromaddr = $socket->recv($buf, 4096)
|| $self->$logger("recv: $!", ERROR);
next if ($!); # continue loop if an error occured
}
} else {
# Receive ipv6 packet
- my $myaddr = $self->{_sock_in_ip6}->sockhost;
+ my $myaddr = $socket->sockhost;
- $fromaddr = $self->{_sock_in_ip6}->recv($buf, 4096)
+ $fromaddr = $socket->recv($buf, 4096)
|| $self->$logger("recv: $!", ERROR);
next if ($!); # continue loop if an error occured
$self->$logger("recv: $buf", INFO);