Subject: | Patch for Class, Zone, Conditionals, and a few parsing bugs |
I'm attaching a patch file that fixes Class, Zones, Conditionals, and
some parsing errors I was getting on my dhcpd.conf file.
I'd really like to give you a copy of my dhcpd.conf for testing because
it's 400Kb and does some interesting things, but it has some customer
data so I want to clean it up before giving it out.
I'll give some examples though:
Keys were failing because a newline wasn't an accepted possible
termination for the regex. That should be fixed now.
key dhcpserver
{
algorithm hmac-md5;
secret "...";
};
Some of my "option space" don't have encapsulate. I'm not sure if they
work properly without it, but that's how it was given to me by the
vendor. I've changed OptionSpace to not require it now.
option space ubnt;
option ubnt.unifi-address code 1 = ip-address;
Conditionals also work now:
if option vendor-class-identifier = "ubnt"
{
vendor-option-space ubnt;
}
Classes work:
class "SipuraATA"
{
match if (substring(option host-name,0,9) = "SipuraSPA");
}
And finally, Zones are also allowed. These are used when you want to
enable dynamic DNS updates through DHCP:
zone staging.fake-domain-name-here.net
{
primary 1.2.3.4;
key staging-key;
}
I get a test result passed for "make test" but I didn't add any new unit
tests. If that is a problem let me know and I'll write some for the new
things.
Also let me know if it breaks or does something you don't want it to do.
Thanks,
Robert Drake
Subject: | net-isc-dhcpd-class.patch |
From 94a366a025d3430772be833924570219f9993eb6 Mon Sep 17 00:00:00 2001
From: Robert Drake <rdrake@direcpath.net>
Date: Sun, 18 Nov 2012 23:57:11 -0500
Subject: [PATCH 1/4] Added Zone.pm to Config.pm
Fixed Key.pm for keys with opening brackets on the next line
Added last if (/\s*{/); to Role.pm to prevent parse errors on open bracket
lines (this could be made safer by checking to see if the parser is at a point
where it expects an open bracket.
Added lib/Net/ISC/DHCPd/Config/Zone.pm for zone handling.
---
lib/Net/ISC/DHCPd/Config.pm | 1 +
lib/Net/ISC/DHCPd/Config/Key.pm | 2 +-
lib/Net/ISC/DHCPd/Config/Role.pm | 3 +
lib/Net/ISC/DHCPd/Config/Zone.pm | 107 ++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+), 1 deletions(-)
create mode 100644 lib/Net/ISC/DHCPd/Config/Zone.pm
diff --git a/lib/Net/ISC/DHCPd/Config.pm b/lib/Net/ISC/DHCPd/Config.pm
index 55e8dd1..77ba543 100644
--- a/lib/Net/ISC/DHCPd/Config.pm
+++ b/lib/Net/ISC/DHCPd/Config.pm
@@ -116,6 +116,7 @@ __PACKAGE__->create_children(qw/
Net::ISC::DHCPd::Config::Group
Net::ISC::DHCPd::Config::Block
Net::ISC::DHCPd::Config::KeyValue
+ Net::ISC::DHCPd::Config::Zone
/);
sub _build_root { $_[0] }
diff --git a/lib/Net/ISC/DHCPd/Config/Key.pm b/lib/Net/ISC/DHCPd/Config/Key.pm
index 442bb2e..f274684 100644
--- a/lib/Net/ISC/DHCPd/Config/Key.pm
+++ b/lib/Net/ISC/DHCPd/Config/Key.pm
@@ -46,7 +46,7 @@ has [qw/ name algorithm secret /] => (
);
sub _build_children { [undef] }
-sub _build_regex { qr{^\s* key \s (")?(\S+)\1 }x }
+sub _build_regex { qr{^\s* key \s (")?(\S+)(\1|$) }x }
=head1 METHODS
diff --git a/lib/Net/ISC/DHCPd/Config/Role.pm b/lib/Net/ISC/DHCPd/Config/Role.pm
index 2d65563..c8bd557 100644
--- a/lib/Net/ISC/DHCPd/Config/Role.pm
+++ b/lib/Net/ISC/DHCPd/Config/Role.pm
@@ -291,6 +291,9 @@ sub parse {
last LINE;
}
}
+ elsif($line =~ /^\s*{/) {
+ next LINE;
+ }
elsif($line =~ /^\s*$/o) {
next LINE;
}
diff --git a/lib/Net/ISC/DHCPd/Config/Zone.pm b/lib/Net/ISC/DHCPd/Config/Zone.pm
new file mode 100644
index 0000000..1df89fd
--- /dev/null
+++ b/lib/Net/ISC/DHCPd/Config/Zone.pm
@@ -0,0 +1,107 @@
+package Net::ISC::DHCPd::Config::Zone;
+
+=head1 NAME
+
+Net::ISC::DHCPd::Config::Key - Server key
+
+=head1 DESCRIPTION
+
+See L<Net::ISC::DHCPd::Config::Role> for methods and attributes without
+documentation.
+
+An instance from this class, comes from / will produce the block below:
+
+ $name_attribute_value $value_attribute_value;
+
+ key "$name" {
+ algorithm $algorithm;
+ secret "$secret";
+ };
+
+=head1 SYNOPSIS
+
+See L<Net::ISC::DHCPd::Config/SYNOPSIS>.
+
+=cut
+
+use Moose;
+
+with 'Net::ISC::DHCPd::Config::Role';
+
+=head1 ATTRIBUTES
+
+=head2 name
+
+Name of the key - See L</DESCRIPTION> for details.
+
+=head2 algorithm
+
+=head2 secret
+
+=cut
+
+has [qw/ name key primary /] => (
+ is => 'rw', # TODO: WILL PROBABLY CHANGE!
+ isa => 'Str',
+);
+
+sub _build_children { [undef] }
+# not sure if this can be quoted or not
+sub _build_regex { qr{^\s* zone \s (")?(\S+)(\1|$) }x }
+
+=head1 METHODS
+
+=head2 slurp
+
+This method is used by L<Net::ISC::DHCPd::Config::Role/parse>, and will
+slurp the content of the function, instead of trying to parse the
+statements.
+
+=cut
+
+sub slurp {
+ my($self, $line) = @_;
+
+ return 'last' if($line =~ /^\s*}/);
+ # not sure if these can really be quoted
+ $self->primary($1) if($line =~ /primary \s+ (\S+);/x);
+ $self->key($2) if($line =~ /key \s+ ("?)(\S+)\1;/x);
+ return 'next';
+}
+
+=head2 captured_to_args
+
+See L<Net::ISC::DHCPd::Config::Role/captured_to_args>.
+
+=cut
+
+sub captured_to_args {
+ return { name => $_[2] }; # $_[1] == quote or empty string
+}
+
+=head2 generate
+
+See L<Net::ISC::DHCPd::Config::Role/generate>.
+
+=cut
+
+sub generate {
+ my $self = shift;
+
+ return(
+ sprintf('zone %s {', $self->name),
+ $self->primary ? (sprintf ' primary %s;', $self->primary) : (),
+ $self->key ? (sprintf ' key %s;', $self->key) : (),
+ '}', # TODO: should this really be here?
+ );
+}
+
+=head1 COPYRIGHT & LICENSE
+
+=head1 AUTHOR
+
+See L<Net::ISC::DHCPd>.
+
+=cut
+
+1;
--
1.7.2.5
From baf89d56a498689f3557f58cdceadbcf5120bbd5 Mon Sep 17 00:00:00 2001
From: Robert Drake <rdrake@direcpath.net>
Date: Mon, 19 Nov 2012 00:17:39 -0500
Subject: [PATCH 2/4] Fixed documentation in Zone.pm
---
lib/Net/ISC/DHCPd/Config/Zone.pm | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/Net/ISC/DHCPd/Config/Zone.pm b/lib/Net/ISC/DHCPd/Config/Zone.pm
index 1df89fd..1375291 100644
--- a/lib/Net/ISC/DHCPd/Config/Zone.pm
+++ b/lib/Net/ISC/DHCPd/Config/Zone.pm
@@ -2,7 +2,7 @@ package Net::ISC::DHCPd::Config::Zone;
=head1 NAME
-Net::ISC::DHCPd::Config::Key - Server key
+Net::ISC::DHCPd::Config::Zone - Server Zone
=head1 DESCRIPTION
@@ -13,9 +13,9 @@ An instance from this class, comes from / will produce the block below:
$name_attribute_value $value_attribute_value;
- key "$name" {
- algorithm $algorithm;
- secret "$secret";
+ zone $name {
+ primary $primary;
+ key $key;
};
=head1 SYNOPSIS
@@ -32,11 +32,11 @@ with 'Net::ISC::DHCPd::Config::Role';
=head2 name
-Name of the key - See L</DESCRIPTION> for details.
+Name of the Zone - See L</DESCRIPTION> for details.
-=head2 algorithm
+=head2 primary
-=head2 secret
+=head2 key
=cut
--
1.7.2.5
From c941f48b12bf0da94db0c915ffa441cc737a052a Mon Sep 17 00:00:00 2001
From: Robert Drake <rdrake@direcpath.net>
Date: Mon, 19 Nov 2012 00:24:25 -0500
Subject: [PATCH 3/4] Added Class to tracked values
---
lib/Net/ISC/DHCPd/Config.pm | 1 +
lib/Net/ISC/DHCPd/Config/Class.pm | 79 +++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 0 deletions(-)
create mode 100644 lib/Net/ISC/DHCPd/Config/Class.pm
diff --git a/lib/Net/ISC/DHCPd/Config.pm b/lib/Net/ISC/DHCPd/Config.pm
index 77ba543..6f14dc0 100644
--- a/lib/Net/ISC/DHCPd/Config.pm
+++ b/lib/Net/ISC/DHCPd/Config.pm
@@ -106,6 +106,7 @@ with 'Net::ISC::DHCPd::Config::Root';
__PACKAGE__->create_children(qw/
Net::ISC::DHCPd::Config::Host
+ Net::ISC::DHCPd::Config::Class
Net::ISC::DHCPd::Config::Subnet
Net::ISC::DHCPd::Config::SharedNetwork
Net::ISC::DHCPd::Config::Function
diff --git a/lib/Net/ISC/DHCPd/Config/Class.pm b/lib/Net/ISC/DHCPd/Config/Class.pm
new file mode 100644
index 0000000..0562da4
--- /dev/null
+++ b/lib/Net/ISC/DHCPd/Config/Class.pm
@@ -0,0 +1,79 @@
+package Net::ISC::DHCPd::Config::Class;
+
+=head1 NAME
+
+Net::ISC::DHCPd::Config::Class;
+
+=head1 DESCRIPTION
+
+See L<Net::ISC::DHCPd::Config::Role> for methods and attributes without
+documentation.
+
+An instance from this class, comes from / will produce the block below:
+
+ class "$name" {
+ ...
+ }
+
+=head1 SYNOPSIS
+
+See L<Net::ISC::DHCPd::Config/SYNOPSIS>.
+
+=cut
+
+use Moose;
+
+with 'Net::ISC::DHCPd::Config::Role';
+
+=head1 ATTRIBUTES
+
+=head2 name
+
+Name of the key - See L</DESCRIPTION> for details.
+
+=head2 algorithm
+
+=head2 secret
+
+=cut
+
+# match will get treated as a KeyValue
+__PACKAGE__->create_children(qw/
+ Net::ISC::DHCPd::Config::Option
+ Net::ISC::DHCPd::Config::KeyValue
+/);
+
+sub _build_regex { qr{^\s* class \s (")?(.*?)(\1|$) }x }
+
+=head1 METHODS
+
+=head2 captured_to_args
+
+See L<Net::ISC::DHCPd::Config::Role/captured_to_args>.
+
+=cut
+
+sub captured_to_args {
+ return { name => $_[2] }; # $_[1] == quote or empty string
+}
+
+=head2 generate
+
+See L<Net::ISC::DHCPd::Config::Role/generate>.
+
+=cut
+
+sub generate {
+ my $self = shift;
+ return sprintf('class "%s" {', $self->name), $self->_generate_config_from_children, '}';
+}
+
+=head1 COPYRIGHT & LICENSE
+
+=head1 AUTHOR
+
+See L<Net::ISC::DHCPd>.
+
+=cut
+
+1;
--
1.7.2.5
From f39e61bb93768cbc447af396f9979d4d1ca5595e Mon Sep 17 00:00:00 2001
From: Robert Drake <rdrake@direcpath.net>
Date: Mon, 19 Nov 2012 00:56:09 -0500
Subject: [PATCH 4/4] Small fixes to Class. Added Condtional to Config.pm. Fixed OptionSpace to
not require encapsulate line.
---
lib/Net/ISC/DHCPd/Config.pm | 1 +
lib/Net/ISC/DHCPd/Config/Class.pm | 5 +++++
lib/Net/ISC/DHCPd/Config/OptionSpace.pm | 4 ++--
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/Net/ISC/DHCPd/Config.pm b/lib/Net/ISC/DHCPd/Config.pm
index 6f14dc0..ef1790d 100644
--- a/lib/Net/ISC/DHCPd/Config.pm
+++ b/lib/Net/ISC/DHCPd/Config.pm
@@ -107,6 +107,7 @@ with 'Net::ISC::DHCPd::Config::Root';
__PACKAGE__->create_children(qw/
Net::ISC::DHCPd::Config::Host
Net::ISC::DHCPd::Config::Class
+ Net::ISC::DHCPd::Config::Conditional
Net::ISC::DHCPd::Config::Subnet
Net::ISC::DHCPd::Config::SharedNetwork
Net::ISC::DHCPd::Config::Function
diff --git a/lib/Net/ISC/DHCPd/Config/Class.pm b/lib/Net/ISC/DHCPd/Config/Class.pm
index 0562da4..8c895f5 100644
--- a/lib/Net/ISC/DHCPd/Config/Class.pm
+++ b/lib/Net/ISC/DHCPd/Config/Class.pm
@@ -37,6 +37,11 @@ Name of the key - See L</DESCRIPTION> for details.
=cut
+has [qw/ name /] => (
+ is => 'rw',
+ isa => 'Str',
+);
+
# match will get treated as a KeyValue
__PACKAGE__->create_children(qw/
Net::ISC::DHCPd::Config::Option
diff --git a/lib/Net/ISC/DHCPd/Config/OptionSpace.pm b/lib/Net/ISC/DHCPd/Config/OptionSpace.pm
index ed9a713..254186f 100644
--- a/lib/Net/ISC/DHCPd/Config/OptionSpace.pm
+++ b/lib/Net/ISC/DHCPd/Config/OptionSpace.pm
@@ -129,11 +129,11 @@ sub generate {
return(
sprintf('option space %s;', $self->prefix),
$self->generate_config_from_children,
- sprintf('option %s code %i = encapsulate %s;',
+ $self->name ? (sprintf 'option %s code %i = encapsulate %s;',
$self->name,
$self->code,
$self->prefix,
- ),
+ ) : (),
);
}
--
1.7.2.5