From cb0a294f51be60d079fd6ddaacd4757a914391b9 Mon Sep 17 00:00:00 2001 From: Michael Rasmussen Date: Tue, 22 Jul 2014 04:00:45 +0200 Subject: [PATCH] Implented config parser --- DHCPServer.pm | 132 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 21 deletions(-) diff --git a/DHCPServer.pm b/DHCPServer.pm index 5b6701f..539093b 100644 --- a/DHCPServer.pm +++ b/DHCPServer.pm @@ -82,6 +82,7 @@ sub new { $self->{_sock_out_ip6} = undef; $self->{_leases} = undef; $self->{_reverse} = undef; + $self->{_config} = undef; $self->{_transaction_ip4} = 0; $self->{_transaction_ip6} = 0; @@ -94,19 +95,28 @@ sub new { $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"); @@ -133,11 +143,8 @@ sub run { $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); @@ -274,19 +281,19 @@ sub run_with_timeout { } 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) { @@ -314,7 +321,7 @@ sub lock { $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; } @@ -323,11 +330,11 @@ sub lock { } 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; @@ -353,7 +360,7 @@ sub unlock { $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; } @@ -421,7 +428,7 @@ sub read_lease_file { 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>; @@ -453,7 +460,7 @@ sub read_lease_file { $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); @@ -467,7 +474,7 @@ sub write_lease_file { 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}) { @@ -482,7 +489,7 @@ sub write_lease_file { } print $fh "}\n"; } - $self->unlock(); + $self->unlock($self->{lease_file}); $res = 1; } else { $self->logger("Could not write leases file", ERROR); @@ -492,6 +499,89 @@ sub write_lease_file { 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); + @tmp = split(/,\s*/, $2); + foreach (@tmp) { + s/^\s+|\s+$//g; + push @vals, $_; + } + $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) = @_; -- 2.39.2