summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2017-04-25 11:51:55 +0200
committerFrancis Dupont <fdupont@isc.org>2018-11-29 16:42:15 +0100
commit07f4ee1db226a3508bca0d7317ffb4d56c2a6090 (patch)
treed713d782a6dcec51d9b7a9f2a8660c2cbfda144b
parent1535eb39453eb84d63c3a9f7ae1835d02e58e934 (diff)
downloadisc-dhcp-07f4ee1db226a3508bca0d7317ffb4d56c2a6090.tar.gz
Checkpoint (debugged shared networks)
-rw-r--r--keama/confparse.c40
-rw-r--r--keama/data.c3
-rw-r--r--keama/doc.txt26
-rw-r--r--keama/parse.c23
-rw-r--r--keama/tests/hostuid4.in42
-rw-r--r--keama/tests/optdatagrouppool4.in42
-rw-r--r--keama/tests/optiondatapool4.in42
-rw-r--r--keama/tests/optiondatapool6.in62
-rw-r--r--keama/tests/orphan6.in62
-rw-r--r--keama/tests/orphan6.out4
-rw-r--r--keama/tests/pool4.in42
-rw-r--r--keama/tests/pool6.in62
-rw-r--r--keama/tests/range4.in42
-rw-r--r--keama/tests/range6.in62
-rw-r--r--keama/tests/shareempty.err6
-rw-r--r--keama/tests/shareempty.msg1
-rw-r--r--keama/tests/shareone4.in425
-rw-r--r--keama/tests/shareone4.out39
-rw-r--r--keama/tests/shareone6.in622
-rw-r--r--keama/tests/shareone6.out33
-rw-r--r--keama/tests/sharetwo4.notyet30
-rw-r--r--keama/tests/tautology.err12
-rw-r--r--keama/tests/tautology.msg1
-rw-r--r--keama/tests/tautologyhexa.notyet12
-rw-r--r--keama/tests/tautologysub.err12
-rw-r--r--keama/tests/tautologysub.msg1
-rw-r--r--keama/tests/unknownspace.err2
27 files changed, 290 insertions, 20 deletions
diff --git a/keama/confparse.c b/keama/confparse.c
index 5a99a932..1c980dbc 100644
--- a/keama/confparse.c
+++ b/keama/confparse.c
@@ -1480,6 +1480,11 @@ subclass_inherit(struct parse *cfile,
appendString(dmsg, print_data_expression(data, &lose));
reduced = reduce_boolean_expression(expr);
+ if ((reduced != NULL) && (reduced->type == ELEMENT_BOOLEAN))
+ parse_error(cfile, "class matching rule reduced to a "
+ "constant boolean expression: %s = %s",
+ print_data_expression(submatch, &lose),
+ print_data_expression(data, &lose));
if ((reduced == NULL) || (reduced->type != ELEMENT_STRING))
return;
if (!lose) {
@@ -1507,6 +1512,10 @@ add_match_class(struct parse *cfile,
comment = createComment(msg->content);
reduced = reduce_boolean_expression(expr);
+ if ((reduced != NULL) && (reduced->type == ELEMENT_BOOLEAN))
+ parse_error(cfile, "'match if' with a constant boolean "
+ "expression %s",
+ print_boolean_expression(expr, &lose));
if ((reduced == NULL) || (reduced->type != ELEMENT_STRING)) {
expr->skip = ISC_TRUE;
cfile->issue_counter++;
@@ -1613,6 +1622,37 @@ parse_shared_net_declaration(struct parse *cfile)
listRemove(subnets, 0);
mapRemove(share, "name");
mapRemove(share, "subnets");
+ /* specific case before calling generic merge */
+ if (mapContains(share, "pools") &&
+ mapContains(subnet, "pools")) {
+ struct element *pools;
+ struct element *sub;
+
+ pools = mapGet(share, "pools");
+ mapRemove(share, "pools");
+ sub = mapGet(subnet, "pools");
+ concat(sub, pools);
+ }
+ if (mapContains(share, "pd-pools") &&
+ mapContains(subnet, "pd-pools")) {
+ struct element *pools;
+ struct element *sub;
+
+ pools = mapGet(share, "pd-pools");
+ mapRemove(share, "pd-pools");
+ sub = mapGet(subnet, "pd-pools");
+ concat(sub, pools);
+ }
+ if (mapContains(share, "option-data") &&
+ mapContains(subnet, "option-data")) {
+ struct element *opt_list;
+ struct element *sub;
+
+ opt_list = mapGet(share, "option-data");
+ mapRemove(share, "option-data");
+ sub = mapGet(subnet, "option-data");
+ merge_option_data(opt_list, sub);
+ }
merge(subnet, share);
if (local_family == AF_INET) {
diff --git a/keama/data.c b/keama/data.c
index f9ccd7cc..6e37d3cc 100644
--- a/keama/data.c
+++ b/keama/data.c
@@ -584,13 +584,14 @@ void
merge(struct element *m, struct element *o)
{
struct element *elem;
+ struct element *ne;
assert(m != NULL);
assert(m->type == ELEMENT_MAP);
assert(o != NULL);
assert(o->type == ELEMENT_MAP);
- TAILQ_FOREACH(elem, &o->value.map_value) {
+ TAILQ_FOREACH_SAFE(elem, &o->value.map_value, ne) {
assert(elem->key != NULL);
TAILQ_REMOVE(&o->value.map_value, elem);
if (!mapContains(m, elem->key)) {
diff --git a/keama/doc.txt b/keama/doc.txt
index f0393cc5..4557e2f3 100644
--- a/keama/doc.txt
+++ b/keama/doc.txt
@@ -455,3 +455,29 @@ Dynamic DNS:
------------
Details are very different so the MA maps only basic parameters
at the global scope.
+
+Expressions:
+------------
+TODO check if data really includes numeric
+ ISC DHCP expressions are typed: boolean, numeric, and data which includes
+ strings and numeric. The default for a literal is to be a string so
+ literal numbers are interpreted in hexadecimal (for a strange consequence
+ https://kb.isc.org/article/AA-00334/56/Do-the-list-of-parameters-in-the-dhcp-parameter-request-list-need-to-be-in-hex.html ).
+ String literals are converted to string elements, hexadecimal literals
+ are converted to const-data maps.
+TODO reduce more hexa aka const-data
+ As booleans are not data there is no way to fix this:
+ /tmp/bool line 9: Expecting a data expression.
+ option ip-forwarding = foo = foo;
+ ^
+ The tautology 'foo = foo' is not a data expression so is rejected by
+ both the MA and dhcpd (BTW the role of the MA is not to fix ISC DHCP
+ shortcomings so it does what it is expected to do here).
+ Note this does not work too:
+ option ip-forwarding = true;
+ because "true" is not a keyword and it is converted into a variable
+ reference... And I expect ISC DHCP makes this true a false at runtime
+ because the variable "true" is not defined by default.
+ Reduced expressions are pretty printed to allow an extra check.
+TODO use precedence to minimize parentheses
+
diff --git a/keama/parse.c b/keama/parse.c
index 808b7352..8e4a8cf6 100644
--- a/keama/parse.c
+++ b/keama/parse.c
@@ -4884,8 +4884,11 @@ putUChar(unsigned char *obuf, uint32_t val)
isc_boolean_t
is_boolean_expression(struct element *expr)
{
- return ((expr->type == ELEMENT_BOOLEAN) ||
- mapContains(expr, "check") ||
+ if (expr->type == ELEMENT_BOOLEAN)
+ return ISC_TRUE;
+ if (expr->type != ELEMENT_MAP)
+ return ISC_FALSE;
+ return (mapContains(expr, "check") ||
mapContains(expr, "exists") ||
mapContains(expr, "variable-exists") ||
mapContains(expr, "equal") ||
@@ -4902,9 +4905,12 @@ is_boolean_expression(struct element *expr)
isc_boolean_t
is_data_expression(struct element *expr)
{
- return ((expr->type == ELEMENT_INTEGER) ||
- (expr->type == ELEMENT_STRING) ||
- mapContains(expr, "substring") ||
+ if ((expr->type == ELEMENT_INTEGER) ||
+ (expr->type == ELEMENT_STRING))
+ return ISC_TRUE;
+ if (expr->type != ELEMENT_MAP)
+ return ISC_FALSE;
+ return (mapContains(expr, "substring") ||
mapContains(expr, "suffix") ||
mapContains(expr, "lowercase") ||
mapContains(expr, "uppercase") ||
@@ -4934,8 +4940,11 @@ is_data_expression(struct element *expr)
isc_boolean_t
is_numeric_expression(struct element *expr)
{
- return ((expr->type == ELEMENT_INTEGER) ||
- mapContains(expr, "extract-int8") ||
+ if (expr->type == ELEMENT_INTEGER)
+ return ISC_TRUE;
+ if (expr->type != ELEMENT_MAP)
+ return ISC_FALSE;
+ return (mapContains(expr, "extract-int8") ||
mapContains(expr, "extract-int16") ||
mapContains(expr, "extract-int32") ||
mapContains(expr, "const-int") ||
diff --git a/keama/tests/hostuid4.in4 b/keama/tests/hostuid4.in4
index 801e7010..3b8238d5 100644
--- a/keama/tests/hostuid4.in4
+++ b/keama/tests/hostuid4.in4
@@ -14,7 +14,7 @@ ignore-client-uids false;
# host declarations
host test1 {
uid 01:02:03:04:05:0a:0b:0c:0d:0e:0f;
- option domain-search example.com, example.org;
+ option domain-search "example.com", "example.org";
default-lease-time 1800;
fixed-address 10.5.5.1, 10.10.10.10;
}
diff --git a/keama/tests/optdatagrouppool4.in4 b/keama/tests/optdatagrouppool4.in4
index 103a4123..886a279e 100644
--- a/keama/tests/optdatagrouppool4.in4
+++ b/keama/tests/optdatagrouppool4.in4
@@ -15,7 +15,7 @@ subnet 10.5.5.0 netmask 255.255.255.224 {
# for a silly reason option-data is not allowed in DHCPv4 pools
# try to fool this rule using a group
group fool {
- option domain-search example.com, example.org;
+ option domain-search "example.com", "example.org";
}
}
}
diff --git a/keama/tests/optiondatapool4.in4 b/keama/tests/optiondatapool4.in4
index 0a143fac..c51887d0 100644
--- a/keama/tests/optiondatapool4.in4
+++ b/keama/tests/optiondatapool4.in4
@@ -10,6 +10,6 @@ subnet 10.5.5.0 netmask 255.255.255.224 {
# avoid empty pool
range 10.5.5.5 10.5.5.10;
# for a silly reason option-data is not allowed in DHCPv4 pools
- option domain-search example.com, example.org;
+ option domain-search "example.com", "example.org";
}
}
diff --git a/keama/tests/optiondatapool6.in6 b/keama/tests/optiondatapool6.in6
index 0cf20522..179c2f5c 100644
--- a/keama/tests/optiondatapool6.in6
+++ b/keama/tests/optiondatapool6.in6
@@ -11,6 +11,6 @@ subnet6 2001::/64 {
range6 2001::100 2001::200;
# for a silly reason option-data is not allowed in DHCPv4 pools
# but allowed in DHCPv6 pools
- option dhcp6.domain-search example.com, example.org;
+ option dhcp6.domain-search "example.com", "example.org";
}
}
diff --git a/keama/tests/orphan6.in6 b/keama/tests/orphan6.in6
index 711bb73d..ed303790 100644
--- a/keama/tests/orphan6.in6
+++ b/keama/tests/orphan6.in6
@@ -9,5 +9,5 @@ default-lease-time 1800;
# orphan reservation
host foobar {
hardware ethernet 00:0B:FD:32:E6:FA;
- option dhcp6.domain-search 2a01:e00::2, 2a01:e00::1;
+ option dhcp6.name-servers 2a01:e00::2, 2a01:e00::1;
}
diff --git a/keama/tests/orphan6.out b/keama/tests/orphan6.out
index cf70d0c1..8be6cd2d 100644
--- a/keama/tests/orphan6.out
+++ b/keama/tests/orphan6.out
@@ -15,8 +15,8 @@
// "option-data": [
// {
// "space": "dhcp6",
-// "name": "domain-search",
-// "code": 24,
+// "name": "dns-servers",
+// "code": 23,
// "data": "2a01:e00::2, 2a01:e00::1"
// }
// ]
diff --git a/keama/tests/pool4.in4 b/keama/tests/pool4.in4
index f834bbc1..db8bc59e 100644
--- a/keama/tests/pool4.in4
+++ b/keama/tests/pool4.in4
@@ -7,7 +7,7 @@ authoritative;
subnet 10.5.5.0 netmask 255.255.255.224 {
# pool declaration
pool {
- option domain-search example.com, example.org;
+ option domain-search "example.com", "example.org";
default-lease-time 1800;
range 10.5.5.5 10.5.5.10;
}
diff --git a/keama/tests/pool6.in6 b/keama/tests/pool6.in6
index 6f52d94f..70c9c709 100644
--- a/keama/tests/pool6.in6
+++ b/keama/tests/pool6.in6
@@ -7,7 +7,7 @@ authoritative;
subnet6 2001::/64 {
# pool declaration
pool6 {
- option dhcp6.domain-search example.com, example.org;
+ option dhcp6.domain-search "example.com", "example.org";
default-lease-time 1800;
range6 2001::100 2001::200;
}
diff --git a/keama/tests/range4.in4 b/keama/tests/range4.in4
index 833da20c..57af6f2c 100644
--- a/keama/tests/range4.in4
+++ b/keama/tests/range4.in4
@@ -6,7 +6,7 @@ authoritative;
# subnet declaration
subnet 10.5.5.0 netmask 255.255.255.224 {
# range declaration
- option domain-search example.com, example.org;
+ option domain-search "example.com", "example.org";
default-lease-time 1800;
range 10.5.5.5 10.5.5.10;
}
diff --git a/keama/tests/range6.in6 b/keama/tests/range6.in6
index 2c141ad7..813b20b5 100644
--- a/keama/tests/range6.in6
+++ b/keama/tests/range6.in6
@@ -6,7 +6,7 @@ authoritative;
# subnet declaration
subnet6 2001::/64 {
# range declaration
- option dhcp6.domain-search example.com, example.org;
+ option dhcp6.domain-search "example.com", "example.org";
default-lease-time 1800;
range6 2001::100 2001::200;
}
diff --git a/keama/tests/shareempty.err b/keama/tests/shareempty.err
new file mode 100644
index 00000000..2e9e3a12
--- /dev/null
+++ b/keama/tests/shareempty.err
@@ -0,0 +1,6 @@
+# bad (no subnet) shared-network declaration config
+
+# shared-network declaration
+shared-network "foobar" {
+ interface "foo";
+}
diff --git a/keama/tests/shareempty.msg b/keama/tests/shareempty.msg
new file mode 100644
index 00000000..fb74cc62
--- /dev/null
+++ b/keama/tests/shareempty.msg
@@ -0,0 +1 @@
+shareempty.err line 6: empty shared-network decl
diff --git a/keama/tests/shareone4.in4 b/keama/tests/shareone4.in4
new file mode 100644
index 00000000..430f7531
--- /dev/null
+++ b/keama/tests/shareone4.in4
@@ -0,0 +1,25 @@
+# DHCPv4 one-subnet shared-network declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# shared-network declaration
+shared-network "foobar" {
+ # interface
+ interface "foo";
+ # option
+ option domain-search "example.com", "example.org";
+ # parameter
+ default-lease-time 1800;
+ # subnet declaration
+ subnet 10.5.5.0 netmask 255.255.255.224 {
+ # redefined parameter
+ default-lease-time 3600;
+ # another option
+ option ip-forwarding true;
+ }
+ # pool (must be after the subnet)
+ pool {
+ range 10.5.5.5 10.5.5.10;
+ }
+}
diff --git a/keama/tests/shareone4.out b/keama/tests/shareone4.out
new file mode 100644
index 00000000..bb5a0165
--- /dev/null
+++ b/keama/tests/shareone4.out
@@ -0,0 +1,39 @@
+{
+ "Dhcp4": {
+ "interfaces-config": {
+ "interfaces": [
+ "foo"
+ ]
+ },
+ "subnet4": [
+ # subnet declaration
+ {
+ "subnet": "10.5.5.0/27",
+ "valid-lifetime": 3600,
+ "option-data": [
+ # another option
+ {
+ "space": "dhcp4",
+ "name": "ip-forwarding",
+ "code": 19,
+ "data": "true"
+ },
+ # interface
+ {
+ "space": "dhcp4",
+ "name": "domain-search",
+ "code": 119,
+ "data": "example.com, example.org"
+ }
+ ],
+ "interface": "foo",
+ "pools": [
+ # pool (must be after the subnet)
+ {
+ "pool": "10.5.5.5 - 10.5.5.10"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/keama/tests/shareone6.in6 b/keama/tests/shareone6.in6
new file mode 100644
index 00000000..8ac35056
--- /dev/null
+++ b/keama/tests/shareone6.in6
@@ -0,0 +1,22 @@
+# DHCPv6 one-subnet shared-network declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# shared-network declaration
+shared-network "foobar" {
+ # interface
+ interface "foo";
+ # option
+ option dhcp6.domain-search "example.com", "example.org";
+ # parameter
+ default-lease-time 1800;
+ # subnet declaration
+ subnet6 2001::/64 {
+ # redefined parameter
+ default-lease-time 3600;
+ # pool
+ range6 2001::1000 2001::2000;
+ }
+ # tried another pool here but DHCPv6 pools are allowed only in subnets
+}
diff --git a/keama/tests/shareone6.out b/keama/tests/shareone6.out
new file mode 100644
index 00000000..a3649c18
--- /dev/null
+++ b/keama/tests/shareone6.out
@@ -0,0 +1,33 @@
+{
+ "Dhcp6": {
+ "interfaces-config": {
+ "interfaces": [
+ "foo"
+ ]
+ },
+ "subnet6": [
+ # subnet declaration
+ {
+ "subnet": "2001::/64",
+ "valid-lifetime": 3600,
+ "pools": [
+ {
+ # pool
+ "pool": "2001::1000 - 2001::2000"
+ }
+ ],
+ "interface": "foo",
+ "option-data": [
+ # interface
+ # option
+ {
+ "space": "dhcp6",
+ "name": "domain-search",
+ "code": 24,
+ "data": "example.com, example.org"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/keama/tests/sharetwo4.notyet b/keama/tests/sharetwo4.notyet
new file mode 100644
index 00000000..fa9c1eb1
--- /dev/null
+++ b/keama/tests/sharetwo4.notyet
@@ -0,0 +1,30 @@
+# DHCPv4 two-subnet shared-network declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# shared-network declaration
+shared-network "foobar" {
+ # interface
+ interface "foo";
+ # option
+ option domain-search "example.com", "example.org";
+ # parameter
+ default-lease-time 1800;
+ # subnet declaration
+ subnet 10.5.5.0 netmask 255.255.255.224 {
+ # redefined parameter
+ default-lease-time 3600;
+ # another option
+ option ip-forwarding true;
+ }
+ # second subnet declaration
+ subnet 10.10.10.0 netmask 255.255.255.224 { }
+ # pools (must be after the subnet)
+ pool {
+ range 10.5.5.5 10.5.5.10;
+ }
+ pool {
+ range 0.10.10.5 0.10.10.10;
+ }
+}
diff --git a/keama/tests/tautology.err b/keama/tests/tautology.err
new file mode 100644
index 00000000..d3a12cec
--- /dev/null
+++ b/keama/tests/tautology.err
@@ -0,0 +1,12 @@
+# bad (tautology) class declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# class declaration
+class "tautology" {
+ # tautology
+ # note that true does not work as it is a variable reference
+ # and for the same reason quotes are needed (or one can use hexa)
+ match if "foo" = "foo";
+}
diff --git a/keama/tests/tautology.msg b/keama/tests/tautology.msg
new file mode 100644
index 00000000..569a2339
--- /dev/null
+++ b/keama/tests/tautology.msg
@@ -0,0 +1 @@
+tautology.err line 11: 'match if' with a constant boolean expression ('foo') = ('foo')
diff --git a/keama/tests/tautologyhexa.notyet b/keama/tests/tautologyhexa.notyet
new file mode 100644
index 00000000..d73ed53c
--- /dev/null
+++ b/keama/tests/tautologyhexa.notyet
@@ -0,0 +1,12 @@
+# bad (tautology) class declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# class declaration
+class "tautology" {
+ # tautology
+ # note that true does not work as it is a variable reference
+ # and for the same reason quotes are needed (or one can use hexa)
+ match if 12:34 = 56:78:9a;
+}
diff --git a/keama/tests/tautologysub.err b/keama/tests/tautologysub.err
new file mode 100644
index 00000000..0004af40
--- /dev/null
+++ b/keama/tests/tautologysub.err
@@ -0,0 +1,12 @@
+# bad (tautology) class declaration config
+
+# authoritative is mandatory
+authoritative;
+
+# superclass declaration
+class "constant" {
+ match "foo";
+}
+
+# subclass declaration
+subclass "constant" "bar";
diff --git a/keama/tests/tautologysub.msg b/keama/tests/tautologysub.msg
new file mode 100644
index 00000000..05f524bd
--- /dev/null
+++ b/keama/tests/tautologysub.msg
@@ -0,0 +1 @@
+tautologysub.err line 12: class matching rule reduced to a constant boolean expression: 'foo' = 'bar'
diff --git a/keama/tests/unknownspace.err b/keama/tests/unknownspace.err
index 29d695cb..8165a972 100644
--- a/keama/tests/unknownspace.err
+++ b/keama/tests/unknownspace.err
@@ -1,4 +1,4 @@
# unknown option config
# unknown option
-option this-space-does-not-exist.domain-search example.com;
+option this-space-does-not-exist.domain-search "example.com";