$self->{_sock_out_ip6} = undef;
$self->{_leases} = undef;
$self->{_reverse} = undef;
+ $self->{_config} = undef;
$self->{_transaction_ip4} = 0;
$self->{_transaction_ip6} = 0;
$self->{domain_name} ||= undef;
$self->{dns_servers} ||= undef;
$self->{ntp_servers} ||= undef;
- $self->{LOG_LEVEL} ||= ERROR;
+ $self->{LOG_LEVEL} = ERROR unless defined $self->{LOG_LEVEL};
$self->{NODAEMON} ||= 0;
$self->{DEBUG} ||= 0;
$self->{timeout} ||= 10;
$self->{lease_file} ||= '/tmp/dhcpd.leases';
+ $self->{conf_file} ||= '/tmp/dhcpd.cfg';
return $self;
}
sub run {
my ($self) = @_;
- my ($sel, @ready, $socket);
+ my ($sel, @ready, $socket, $res);
+ eval {
+ $self->read_config();
+ };
+ if ($@) {
+ my $err = $@;
+ $self->logger($err, ERROR);
+ die $err;
+ }
$self->logger("Starting dhcpd", INFO);
if ($self->{NODAEMON} < 1) {
$self->logger("Entering Daemon mode");
$self->logger("Now in Daemon mode", INFO);
}
- my $res = $self->read_lease_file();
- do {
- $self->logger("Couldn't read leases file '$self->{lease_file}'", ERROR);
- die "Couldn't read leases file '$self->{lease_file}'";
- } unless $res;
+ $res = $self->read_lease_file();
+ $self->logger("Starting with empty leases file '$self->{lease_file}'", INFO) unless $res;
$self->logger("Initialization complete", INFO);
}
sub lock {
- my ($self, $shared) = @_;
+ my ($self, $file, $shared) = @_;
my $mode = $shared ? LOCK_SH : LOCK_EX;
my $lock_func = sub {
if ($mode == LOCK_SH) {
- $self->{file_handle} = new IO::File ("<$self->{lease_file}") ||
- die "can't open file for read - $!";
+ $self->{file_handle} = new IO::File ("<$file") ||
+ die "can't open file '$file' for read - $!";
} else {
- $self->{file_handle} = new IO::File (">$self->{lease_file}") ||
- die "can't open file write - $!";
+ $self->{file_handle} = new IO::File (">$file") ||
+ die "can't open file '$file' for write - $!";
}
- $self->logger("trying to aquire lock on '$self->{lease_file}'...");
+ $self->logger("trying to aquire lock on '$file'...");
if (!flock ($self->{file_handle}, $mode|LOCK_NB)) {
my $success;
while(1) {
$res = $self->run_with_timeout($lock_func);
};
if ($@) {
- $self->logger("can't lock file '$self->{lease_file}' - $@", ERROR);
+ $self->logger("can't lock file '$file' - $@", ERROR);
$self->{file_handle} = undef;
return undef;
}
}
sub unlock {
- my ($self) = @_;
+ my ($self, $file) = @_;
return '' unless($self->{file_handle});
my $unlock_func = sub {
- $self->logger("trying to unlock '$self->{lease_file}'...");
+ $self->logger("trying to unlock '$file'...");
if (!flock($self->{file_handle}, LOCK_UN)) {
my $success;
$res = $self->run_with_timeout($unlock_func);
};
if ($@) {
- $self->logger("can't lock file '$self->{lease_file}' - $@", ERROR);
+ $self->logger("can't lock file '$file' - $@", ERROR);
$self->{file_handle} = undef;
$res = undef;
}
my ($res, $key, $lease);
my $error = 0;
- $self->lock(1);
+ $self->lock($self->{lease_file}, 1);
if ($self->{file_handle}) {
my $fh = $self->{file_handle};
my @lines = <$fh>;
$self->logger("Key: $key");
} else {
next if $error;
- next if ($_ =~ /^\s*}\s*/ || $_ =~ /^\s*$/);
+ next if ($_ =~ /^\s*}\s*/ || $_ =~ /^\s*$/ || $_ =~ /^\s*#.*/);
if ($_ =~ /^\s*(starts|ends|binding state|hardware ethernet|client-hostname)\s+(.+)\s*;/) {
$lease->{$1} = $2;
$self->logger("Key: $1 Value: $2");
$self->add_lease($key, $lease);
}
$self->logger("Leases data structure: \n" . Dumper($self->{_leases}));
- $self->unlock();
+ $self->unlock($self->{lease_file});
$res = 1;
} else {
$self->logger("Could not read leases file", ERROR);
my ($self) = @_;
my $res;
- $res = $self->lock(0);
+ $res = $self->lock($self->{lease_file}, 0);
if ($self->{file_handle}) {
my $fh = $self->{file_handle};
while ((my $lease, my $elems) = each $self->{_leases}) {
}
print $fh "}\n";
}
- $self->unlock();
+ $self->unlock($self->{lease_file});
$res = 1;
} else {
$self->logger("Could not write leases file", ERROR);
return $res;
}
+#subnet 192.168.9.0 netmask 255.255.255.0 {
+# range 192.168.9.2 192.168.9.100;
+# ttl 7200;
+# rttl 3600;
+# router 192.168.9.254;
+# dns-servers 192.168.2.201;
+# ntp-servers 192.168.9.254;
+# broadcast 192.168.9.255;
+# domain-name "foo.bar";
+# {
+# allow 001cc0c33317,001cc0c33318,001cc0c33319,001cc0c33320;
+# static 001cc0c33317 192.168.9.100,001cc0c33318 192.168.9.200;
+# }
+#}
+sub read_config {
+ my ($self) = @_;
+ my ($res, $key, $netmask, $config, $subopt);
+
+ $self->lock($self->{conf_file}, 1);
+ if ($self->{file_handle}) {
+ my $fh = $self->{file_handle};
+ my @lines = <$fh>;
+ $subopt = 0;
+ foreach (@lines) {
+ $self->logger("Read: $_");
+ if ($_ =~ /^\s*subnet\s+([\d\.]+)\s+netmask\s+([\d\.]+)\s+{\s*/) {
+ $self->{_config}->{$key} = $config if $config;
+ $key = $1;
+ $config = undef;
+ $config->{netmask} = $2;
+ $self->logger("Key: $key Netmask: $config->{netmask}");
+ } else {
+ next if (($_ =~ /^\s*}\s*/ && ! $subopt) || $_ =~ /^\s*$/ || $_ =~ /^\s*#.*/);
+ if (! $subopt && $_ =~ /^\s*(range|ttl|rttl|router|dns-servers|ntp-servers|broadcast|domain-name)\s+(.+)\s*;/) {
+ $config->{$1} = $2;
+ $self->logger("Key: $1 Value: $2");
+ } elsif ($subopt &&$_ =~ /^\s*}\s*/) {
+ $subopt = 0;
+ } elsif ($subopt || $_ =~ /^\s*{\s*/) {
+ if ($subopt) {
+ if ($_ =~ /^\s*(allow|static)\s+(.+)\s*;/) {
+ my (@vals, @tmp);
+ @vals = split(/\s*,\s*/, $2);
+ $config->{$1} = [@vals];
+ $self->logger("Key: $1 Value: $2");
+ } else {
+ $key = 'UNDEF' unless $key;
+ my $err = "$key: 'suboptions' Bad format";
+ $self->logger($err, ERROR);
+ $key = undef;
+ $config = undef;
+ die $err;
+ }
+ } else {
+ $subopt = 1;
+ }
+ } else {
+ $key = 'UNDEF' unless $key;
+ my $err = "$key: Bad format";
+ $self->logger($err, ERROR);
+ $key = undef;
+ $config = undef;
+ die $err;
+ }
+ }
+ }
+ if ($config) {
+ $self->{_config}->{$key} = $config;
+ }
+ $self->logger("Config data structure: \n" . Dumper($self->{_config}));
+ $self->unlock($self->{conf_file});
+ if (!$self->{_config}) {
+ die "Empty config file";
+ }
+ } else {
+ die "Could not read config file";
+ }
+}
+
sub logger {
my ($self, $message, $level) = @_;