egberts/bind9_parser

masters statement in zone config is too strict

tduboys opened this issue · 1 comments

Hi,

It seems there is a parsing error on masters statement in zone declaration.
following this config : http://www.zytrax.com/books/dns/ch7/zone.html#masters

from bind9_parser import *
zone = """
zone "example.com" in {
    type slave;
    file "slave/example.com";
    masters mymaster {192.168.2.7;};
};
"""
result = clause_statements.parseString(zone)
print(result)

result is, as expected :
[['"example.com"', 'in', 'slave', '"slave/example.com"', ['mymaster', [['192.168.2.7']]]]]

but with

zone = """
zone "example.com" in {
    type slave;
    file "slave/example.com";
    masters {192.168.2.7;};
};
"""

I got a parsing exception :
pyparsing.ParseException: Expected {W:(ABCD...) | W:(ABCD...) | <master_name>}, found '{' (at char 83), (line:5, col:13)

Also with

zone = """
zone "example.com" in {
    type slave;
    file "slave/example.com";
    masters port 1127 {192.168.2.7; 10.2.3.15 key zt-key; 2001:db8:0:1::15 port 1128;};
};
"""

that is the example from zytrax, I got
pyparsing.ParseException: Expected "{", found '1' (at char 88), (line:5, col:18)

It appears that, after a masters statement, the parsers looks for a word, and a {, but description is optional, and other statements can be present.
Both 3 examples here are valid with named-checkconf bind tool.

OH, one other thing: The EBNF syntax is drastically different between

  • zone-specific masters statement (introduced in v9.0)
  • top-level masters clause (introduced in v9.3)

EBNF for masters statement (inside the zone) is initially:

masters [ port ip_port ] { ip_addr; [ ip_addr; ... ] }; 

EBNF for masters clause (top-level) is (since v9.3):

masters <string> [ port <integer> ] { ( <masters> | <ipv4_address> [ port
    <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };

Ergo

So, using the master label is only limited to the clause (top-level).

If you wanted to use the actual master label inside the zone, (that was defined at the top-level), then you would do this:

masters my_master_label { 192.168.1.1; };

zone "example.test" {
    masters port 123 { my_master_label; };
};

I am closing this without a fix.