xref: /openbsd-src/usr.sbin/nsd/zparser.y (revision 063644e9d47fc0eb300e319033fb55d96345aa40)
162ac0c33Sjakob %{
262ac0c33Sjakob /*
362ac0c33Sjakob  * zyparser.y -- yacc grammar for (DNS) zone files
462ac0c33Sjakob  *
5dd5b221eSsthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
662ac0c33Sjakob  *
762ac0c33Sjakob  * See LICENSE for the license.
862ac0c33Sjakob  *
962ac0c33Sjakob  */
1062ac0c33Sjakob 
11d11a62c8Ssthen #include "config.h"
1262ac0c33Sjakob 
1362ac0c33Sjakob #include <stdarg.h>
1462ac0c33Sjakob #include <stdio.h>
1562ac0c33Sjakob #include <string.h>
1662ac0c33Sjakob 
1762ac0c33Sjakob #include "dname.h"
1862ac0c33Sjakob #include "namedb.h"
1962ac0c33Sjakob #include "zonec.h"
2062ac0c33Sjakob 
2162ac0c33Sjakob /* these need to be global, otherwise they cannot be used inside yacc */
2262ac0c33Sjakob zparser_type *parser;
2362ac0c33Sjakob 
2462ac0c33Sjakob #ifdef __cplusplus
2562ac0c33Sjakob extern "C"
2662ac0c33Sjakob #endif /* __cplusplus */
2762ac0c33Sjakob int yywrap(void);
2862ac0c33Sjakob 
2962ac0c33Sjakob /* this hold the nxt bits */
3062ac0c33Sjakob static uint8_t nxtbits[16];
3162ac0c33Sjakob static int dlv_warn = 1;
3262ac0c33Sjakob 
3362ac0c33Sjakob /* 256 windows of 256 bits (32 bytes) */
3462ac0c33Sjakob /* still need to reset the bastard somewhere */
3562ac0c33Sjakob static uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
3662ac0c33Sjakob 
3762ac0c33Sjakob /* hold the highest rcode seen in a NSEC rdata , BUG #106 */
3862ac0c33Sjakob uint16_t nsec_highest_rcode;
3962ac0c33Sjakob 
4062ac0c33Sjakob void yyerror(const char *message);
4162ac0c33Sjakob 
4262ac0c33Sjakob #ifdef NSEC3
4362ac0c33Sjakob /* parse nsec3 parameters and add the (first) rdata elements */
4462ac0c33Sjakob static void
4562ac0c33Sjakob nsec3_add_params(const char* hash_algo_str, const char* flag_str,
4662ac0c33Sjakob 	const char* iter_str, const char* salt_str, int salt_len);
4762ac0c33Sjakob #endif /* NSEC3 */
4862ac0c33Sjakob 
4962ac0c33Sjakob %}
5062ac0c33Sjakob %union {
5162ac0c33Sjakob 	domain_type	 *domain;
5262ac0c33Sjakob 	const dname_type *dname;
5362ac0c33Sjakob 	struct lex_data	  data;
5462ac0c33Sjakob 	uint32_t	  ttl;
5562ac0c33Sjakob 	uint16_t	  klass;
5662ac0c33Sjakob 	uint16_t	  type;
5762ac0c33Sjakob 	uint16_t	 *unknown;
5862ac0c33Sjakob }
5962ac0c33Sjakob 
6062ac0c33Sjakob /*
6162ac0c33Sjakob  * Tokens to represent the known RR types of DNS.
6262ac0c33Sjakob  */
6362ac0c33Sjakob %token <type> T_A T_NS T_MX T_TXT T_CNAME T_AAAA T_PTR T_NXT T_KEY T_SOA T_SIG
6462ac0c33Sjakob %token <type> T_SRV T_CERT T_LOC T_MD T_MF T_MB T_MG T_MR T_NULL T_WKS T_HINFO
6562ac0c33Sjakob %token <type> T_MINFO T_RP T_AFSDB T_X25 T_ISDN T_RT T_NSAP T_NSAP_PTR T_PX
6662ac0c33Sjakob %token <type> T_GPOS T_EID T_NIMLOC T_ATMA T_NAPTR T_KX T_A6 T_DNAME T_SINK
6762ac0c33Sjakob %token <type> T_OPT T_APL T_UINFO T_UID T_GID T_UNSPEC T_TKEY T_TSIG T_IXFR
6862ac0c33Sjakob %token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
69e3d8a0a5Ssthen %token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA T_URI
7003739794Sbrad %token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA T_CDS T_CDNSKEY
71*063644e9Sflorian %token <type> T_OPENPGPKEY T_CSYNC T_ZONEMD T_AVC T_SMIMEA T_SVCB T_HTTPS
7262ac0c33Sjakob 
7362ac0c33Sjakob /* other tokens */
7462ac0c33Sjakob %token	       DOLLAR_TTL DOLLAR_ORIGIN NL SP
758d298c9fSsthen %token <data>  QSTR STR PREV BITLAB
7662ac0c33Sjakob %token <ttl>   T_TTL
7762ac0c33Sjakob %token <klass> T_RRCLASS
7862ac0c33Sjakob 
7962ac0c33Sjakob /* unknown RRs */
8062ac0c33Sjakob %token	       URR
8162ac0c33Sjakob %token <type>  T_UTYPE
8262ac0c33Sjakob 
8362ac0c33Sjakob %type <type>	type_and_rdata
8462ac0c33Sjakob %type <domain>	owner dname abs_dname
8562ac0c33Sjakob %type <dname>	rel_dname label
8662ac0c33Sjakob %type <data>	wire_dname wire_abs_dname wire_rel_dname wire_label
878d298c9fSsthen %type <data>	str concatenated_str_seq str_sp_seq str_dot_seq
88*063644e9Sflorian %type <data>	unquoted_dotted_str dotted_str svcparam svcparams
8962ac0c33Sjakob %type <data>	nxt_seq nsec_more
9062ac0c33Sjakob %type <unknown> rdata_unknown
9162ac0c33Sjakob 
9262ac0c33Sjakob %%
9362ac0c33Sjakob lines:	/* empty file */
9462ac0c33Sjakob     |	lines line
9562ac0c33Sjakob     ;
9662ac0c33Sjakob 
9762ac0c33Sjakob line:	NL
9862ac0c33Sjakob     |	sp NL
9962ac0c33Sjakob     |	PREV NL		{}    /* Lines containing only whitespace.  */
10062ac0c33Sjakob     |	ttl_directive
10162ac0c33Sjakob 	{
1028d8f1862Ssthen 	    region_free_all(parser->rr_region);
1038d8f1862Ssthen 	    parser->current_rr.type = 0;
1048d8f1862Ssthen 	    parser->current_rr.rdata_count = 0;
1058d8f1862Ssthen 	    parser->current_rr.rdatas = parser->temporary_rdatas;
10662ac0c33Sjakob 	    parser->error_occurred = 0;
10762ac0c33Sjakob     }
10862ac0c33Sjakob     |	origin_directive
10962ac0c33Sjakob 	{
1108d8f1862Ssthen 	    region_free_all(parser->rr_region);
1118d8f1862Ssthen 	    parser->current_rr.type = 0;
1128d8f1862Ssthen 	    parser->current_rr.rdata_count = 0;
1138d8f1862Ssthen 	    parser->current_rr.rdatas = parser->temporary_rdatas;
11462ac0c33Sjakob 	    parser->error_occurred = 0;
11562ac0c33Sjakob     }
11662ac0c33Sjakob     |	rr
11762ac0c33Sjakob     {	/* rr should be fully parsed */
11862ac0c33Sjakob 	    if (!parser->error_occurred) {
11962ac0c33Sjakob 			    parser->current_rr.rdatas
1208d8f1862Ssthen 				    =(rdata_atom_type *)region_alloc_array_init(
12162ac0c33Sjakob 					    parser->region,
12262ac0c33Sjakob 					    parser->current_rr.rdatas,
1238d8f1862Ssthen 					    parser->current_rr.rdata_count,
1248d8f1862Ssthen 					    sizeof(rdata_atom_type));
12562ac0c33Sjakob 
12662ac0c33Sjakob 			    process_rr();
12762ac0c33Sjakob 	    }
12862ac0c33Sjakob 
12962ac0c33Sjakob 	    region_free_all(parser->rr_region);
13062ac0c33Sjakob 
13162ac0c33Sjakob 	    parser->current_rr.type = 0;
13262ac0c33Sjakob 	    parser->current_rr.rdata_count = 0;
13362ac0c33Sjakob 	    parser->current_rr.rdatas = parser->temporary_rdatas;
13462ac0c33Sjakob 	    parser->error_occurred = 0;
13562ac0c33Sjakob     }
13662ac0c33Sjakob     |	error NL
13762ac0c33Sjakob     ;
13862ac0c33Sjakob 
1392fd875a4Ssthen /* needed to cope with ( and ) in arbitrary places */
14062ac0c33Sjakob sp:	SP
14162ac0c33Sjakob     |	sp SP
14262ac0c33Sjakob     ;
14362ac0c33Sjakob 
1448d298c9fSsthen str:	STR | QSTR;
1458d298c9fSsthen 
14662ac0c33Sjakob trail:	NL
14762ac0c33Sjakob     |	sp NL
14862ac0c33Sjakob     ;
14962ac0c33Sjakob 
1508d298c9fSsthen ttl_directive:	DOLLAR_TTL sp str trail
15162ac0c33Sjakob     {
15262ac0c33Sjakob 	    parser->default_ttl = zparser_ttl2int($3.str, &(parser->error_occurred));
15362ac0c33Sjakob 	    if (parser->error_occurred == 1) {
15462ac0c33Sjakob 		    parser->default_ttl = DEFAULT_TTL;
15562ac0c33Sjakob 			parser->error_occurred = 0;
15662ac0c33Sjakob 	    }
15762ac0c33Sjakob     }
15862ac0c33Sjakob     ;
15962ac0c33Sjakob 
16062ac0c33Sjakob origin_directive:	DOLLAR_ORIGIN sp abs_dname trail
16162ac0c33Sjakob     {
162dd5b221eSsthen 	    /* if previous origin is unused, remove it, do not leak it */
1638d8f1862Ssthen 	    if(parser->origin != error_domain && parser->origin != $3) {
1648d8f1862Ssthen 		/* protect $3 from deletion, because deldomain walks up */
1658d8f1862Ssthen 		$3->usage ++;
166dd5b221eSsthen 	    	domain_table_deldomain(parser->db, parser->origin);
1678d8f1862Ssthen 		$3->usage --;
1688d8f1862Ssthen 	    }
16962ac0c33Sjakob 	    parser->origin = $3;
17062ac0c33Sjakob     }
17162ac0c33Sjakob     |	DOLLAR_ORIGIN sp rel_dname trail
17262ac0c33Sjakob     {
17362ac0c33Sjakob 	    zc_error_prev_line("$ORIGIN directive requires absolute domain name");
17462ac0c33Sjakob     }
17562ac0c33Sjakob     ;
17662ac0c33Sjakob 
17762ac0c33Sjakob rr:	owner classttl type_and_rdata
17862ac0c33Sjakob     {
17962ac0c33Sjakob 	    parser->current_rr.owner = $1;
18062ac0c33Sjakob 	    parser->current_rr.type = $3;
18162ac0c33Sjakob     }
18262ac0c33Sjakob     ;
18362ac0c33Sjakob 
18462ac0c33Sjakob owner:	dname sp
18562ac0c33Sjakob     {
18662ac0c33Sjakob 	    parser->prev_dname = $1;
18762ac0c33Sjakob 	    $$ = $1;
18862ac0c33Sjakob     }
18962ac0c33Sjakob     |	PREV
19062ac0c33Sjakob     {
19162ac0c33Sjakob 	    $$ = parser->prev_dname;
19262ac0c33Sjakob     }
19362ac0c33Sjakob     ;
19462ac0c33Sjakob 
19562ac0c33Sjakob classttl:	/* empty - fill in the default, def. ttl and IN class */
19662ac0c33Sjakob     {
19762ac0c33Sjakob 	    parser->current_rr.ttl = parser->default_ttl;
19862ac0c33Sjakob 	    parser->current_rr.klass = parser->default_class;
19962ac0c33Sjakob     }
20062ac0c33Sjakob     |	T_RRCLASS sp		/* no ttl */
20162ac0c33Sjakob     {
20262ac0c33Sjakob 	    parser->current_rr.ttl = parser->default_ttl;
20362ac0c33Sjakob 	    parser->current_rr.klass = $1;
20462ac0c33Sjakob     }
20562ac0c33Sjakob     |	T_TTL sp		/* no class */
20662ac0c33Sjakob     {
20762ac0c33Sjakob 	    parser->current_rr.ttl = $1;
20862ac0c33Sjakob 	    parser->current_rr.klass = parser->default_class;
20962ac0c33Sjakob     }
21062ac0c33Sjakob     |	T_TTL sp T_RRCLASS sp	/* the lot */
21162ac0c33Sjakob     {
21262ac0c33Sjakob 	    parser->current_rr.ttl = $1;
21362ac0c33Sjakob 	    parser->current_rr.klass = $3;
21462ac0c33Sjakob     }
21562ac0c33Sjakob     |	T_RRCLASS sp T_TTL sp	/* the lot - reversed */
21662ac0c33Sjakob     {
21762ac0c33Sjakob 	    parser->current_rr.ttl = $3;
21862ac0c33Sjakob 	    parser->current_rr.klass = $1;
21962ac0c33Sjakob     }
22062ac0c33Sjakob     ;
22162ac0c33Sjakob 
22262ac0c33Sjakob dname:	abs_dname
22362ac0c33Sjakob     |	rel_dname
22462ac0c33Sjakob     {
22562ac0c33Sjakob 	    if ($1 == error_dname) {
22662ac0c33Sjakob 		    $$ = error_domain;
2278d8f1862Ssthen 	    } else if(parser->origin == error_domain) {
2288d8f1862Ssthen 		    zc_error("cannot concatenate origin to domain name, because origin failed to parse");
2298d8f1862Ssthen 		    $$ = error_domain;
23062ac0c33Sjakob 	    } else if ($1->name_size + domain_dname(parser->origin)->name_size - 1 > MAXDOMAINLEN) {
23162ac0c33Sjakob 		    zc_error("domain name exceeds %d character limit", MAXDOMAINLEN);
23262ac0c33Sjakob 		    $$ = error_domain;
23362ac0c33Sjakob 	    } else {
23462ac0c33Sjakob 		    $$ = domain_table_insert(
23562ac0c33Sjakob 			    parser->db->domains,
23662ac0c33Sjakob 			    dname_concatenate(
23762ac0c33Sjakob 				    parser->rr_region,
23862ac0c33Sjakob 				    $1,
23962ac0c33Sjakob 				    domain_dname(parser->origin)));
24062ac0c33Sjakob 	    }
24162ac0c33Sjakob     }
24262ac0c33Sjakob     ;
24362ac0c33Sjakob 
24462ac0c33Sjakob abs_dname:	'.'
24562ac0c33Sjakob     {
24662ac0c33Sjakob 	    $$ = parser->db->domains->root;
24762ac0c33Sjakob     }
24862ac0c33Sjakob     |	'@'
24962ac0c33Sjakob     {
25062ac0c33Sjakob 	    $$ = parser->origin;
25162ac0c33Sjakob     }
25262ac0c33Sjakob     |	rel_dname '.'
25362ac0c33Sjakob     {
25462ac0c33Sjakob 	    if ($1 != error_dname) {
25562ac0c33Sjakob 		    $$ = domain_table_insert(parser->db->domains, $1);
25662ac0c33Sjakob 	    } else {
25762ac0c33Sjakob 		    $$ = error_domain;
25862ac0c33Sjakob 	    }
25962ac0c33Sjakob     }
26062ac0c33Sjakob     ;
26162ac0c33Sjakob 
2628d298c9fSsthen label:	str
26362ac0c33Sjakob     {
26462ac0c33Sjakob 	    if ($1.len > MAXLABELLEN) {
26562ac0c33Sjakob 		    zc_error("label exceeds %d character limit", MAXLABELLEN);
26662ac0c33Sjakob 		    $$ = error_dname;
2679c620270Ssthen 	    } else if ($1.len <= 0) {
2689c620270Ssthen 		    zc_error("zero label length");
2699c620270Ssthen 		    $$ = error_dname;
27062ac0c33Sjakob 	    } else {
27162ac0c33Sjakob 		    $$ = dname_make_from_label(parser->rr_region,
27262ac0c33Sjakob 					       (uint8_t *) $1.str,
27362ac0c33Sjakob 					       $1.len);
27462ac0c33Sjakob 	    }
27562ac0c33Sjakob     }
27662ac0c33Sjakob     |	BITLAB
27762ac0c33Sjakob     {
2789c620270Ssthen 	    zc_error("bitlabels are now deprecated. RFC2673 is obsoleted.");
27962ac0c33Sjakob 	    $$ = error_dname;
28062ac0c33Sjakob     }
28162ac0c33Sjakob     ;
28262ac0c33Sjakob 
28362ac0c33Sjakob rel_dname:	label
28462ac0c33Sjakob     |	rel_dname '.' label
28562ac0c33Sjakob     {
28662ac0c33Sjakob 	    if ($1 == error_dname || $3 == error_dname) {
28762ac0c33Sjakob 		    $$ = error_dname;
28862ac0c33Sjakob 	    } else if ($1->name_size + $3->name_size - 1 > MAXDOMAINLEN) {
28962ac0c33Sjakob 		    zc_error("domain name exceeds %d character limit",
29062ac0c33Sjakob 			     MAXDOMAINLEN);
29162ac0c33Sjakob 		    $$ = error_dname;
29262ac0c33Sjakob 	    } else {
29362ac0c33Sjakob 		    $$ = dname_concatenate(parser->rr_region, $1, $3);
29462ac0c33Sjakob 	    }
29562ac0c33Sjakob     }
29662ac0c33Sjakob     ;
29762ac0c33Sjakob 
29862ac0c33Sjakob /*
29962ac0c33Sjakob  * Some dnames in rdata are handled as opaque blobs
30062ac0c33Sjakob  */
30162ac0c33Sjakob 
30262ac0c33Sjakob wire_dname:	wire_abs_dname
30362ac0c33Sjakob     |	wire_rel_dname
304e02bc0dfSflorian     {
305e02bc0dfSflorian 	    /* terminate in root label and copy the origin in there */
306e02bc0dfSflorian 	    if(parser->origin && domain_dname(parser->origin)) {
307e02bc0dfSflorian 		    $$.len = $1.len + domain_dname(parser->origin)->name_size;
308e02bc0dfSflorian 		    if ($$.len > MAXDOMAINLEN)
309e02bc0dfSflorian 			    zc_error("domain name exceeds %d character limit",
310e02bc0dfSflorian 				     MAXDOMAINLEN);
311e02bc0dfSflorian 		    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
312e02bc0dfSflorian 		    memmove($$.str, $1.str, $1.len);
313e02bc0dfSflorian 		    memmove($$.str + $1.len, dname_name(domain_dname(parser->origin)),
314e02bc0dfSflorian 			domain_dname(parser->origin)->name_size);
315e02bc0dfSflorian 	    } else {
316e02bc0dfSflorian 		    $$.len = $1.len + 1;
317e02bc0dfSflorian 		    if ($$.len > MAXDOMAINLEN)
318e02bc0dfSflorian 			    zc_error("domain name exceeds %d character limit",
319e02bc0dfSflorian 				     MAXDOMAINLEN);
320e02bc0dfSflorian 		    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
321e02bc0dfSflorian 		    memmove($$.str, $1.str, $1.len);
322e02bc0dfSflorian 		    $$.str[ $1.len ] = 0;
323e02bc0dfSflorian 	    }
324e02bc0dfSflorian     }
32562ac0c33Sjakob     ;
32662ac0c33Sjakob 
32762ac0c33Sjakob wire_abs_dname:	'.'
32862ac0c33Sjakob     {
329e02bc0dfSflorian 	    char *result = (char *) region_alloc(parser->rr_region, 1);
33062ac0c33Sjakob 	    result[0] = 0;
33162ac0c33Sjakob 	    $$.str = result;
33262ac0c33Sjakob 	    $$.len = 1;
33362ac0c33Sjakob     }
334e02bc0dfSflorian     |	'@'
335e02bc0dfSflorian     {
336e02bc0dfSflorian 	    if(parser->origin && domain_dname(parser->origin)) {
337e02bc0dfSflorian 		    $$.len = domain_dname(parser->origin)->name_size;
338e02bc0dfSflorian 		    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
339e02bc0dfSflorian 		    memmove($$.str, dname_name(domain_dname(parser->origin)), $$.len);
340e02bc0dfSflorian 	    } else {
341e02bc0dfSflorian 		    $$.len = 1;
342e02bc0dfSflorian 		    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
343e02bc0dfSflorian 		    $$.str[0] = 0;
344e02bc0dfSflorian 	    }
345e02bc0dfSflorian     }
34662ac0c33Sjakob     |	wire_rel_dname '.'
34762ac0c33Sjakob     {
34862ac0c33Sjakob 	    $$.len = $1.len + 1;
349e02bc0dfSflorian 	    if ($$.len > MAXDOMAINLEN)
350e02bc0dfSflorian 		    zc_error("domain name exceeds %d character limit",
351e02bc0dfSflorian 			     MAXDOMAINLEN);
352e02bc0dfSflorian 	    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
353e02bc0dfSflorian 	    memcpy($$.str, $1.str, $1.len);
354e02bc0dfSflorian 	    $$.str[$1.len] = 0;
35562ac0c33Sjakob     }
35662ac0c33Sjakob     ;
35762ac0c33Sjakob 
3588d298c9fSsthen wire_label:	str
35962ac0c33Sjakob     {
36062ac0c33Sjakob 	    char *result = (char *) region_alloc(parser->rr_region,
36162ac0c33Sjakob 						 $1.len + 1);
36262ac0c33Sjakob 
36362ac0c33Sjakob 	    if ($1.len > MAXLABELLEN)
36462ac0c33Sjakob 		    zc_error("label exceeds %d character limit", MAXLABELLEN);
36562ac0c33Sjakob 
36662ac0c33Sjakob 	    /* make label anyway */
36762ac0c33Sjakob 	    result[0] = $1.len;
368e02bc0dfSflorian 	    memmove(result+1, $1.str, $1.len);
36962ac0c33Sjakob 
37062ac0c33Sjakob 	    $$.str = result;
37162ac0c33Sjakob 	    $$.len = $1.len + 1;
37262ac0c33Sjakob     }
37362ac0c33Sjakob     ;
37462ac0c33Sjakob 
37562ac0c33Sjakob wire_rel_dname:	wire_label
37662ac0c33Sjakob     |	wire_rel_dname '.' wire_label
37762ac0c33Sjakob     {
378e02bc0dfSflorian 	    $$.len = $1.len + $3.len;
379e02bc0dfSflorian 	    if ($$.len > MAXDOMAINLEN)
38062ac0c33Sjakob 		    zc_error("domain name exceeds %d character limit",
38162ac0c33Sjakob 			     MAXDOMAINLEN);
382e02bc0dfSflorian 	    $$.str = (char *) region_alloc(parser->rr_region, $$.len);
383e02bc0dfSflorian 	    memmove($$.str, $1.str, $1.len);
384e02bc0dfSflorian 	    memmove($$.str + $1.len, $3.str, $3.len);
38562ac0c33Sjakob     }
38662ac0c33Sjakob     ;
38762ac0c33Sjakob 
3888d298c9fSsthen str_seq:	unquoted_dotted_str
38962ac0c33Sjakob     {
3909c620270Ssthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $1.str, $1.len), 1);
39162ac0c33Sjakob     }
3928d298c9fSsthen     |	QSTR
3938d298c9fSsthen     {
3948d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $1.str, $1.len), 1);
3958d298c9fSsthen     }
3968d298c9fSsthen     |	QSTR unquoted_dotted_str
3978d298c9fSsthen     {
3988d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $1.str, $1.len), 1);
3998d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $2.str, $2.len), 0);
4008d298c9fSsthen     }
4018d298c9fSsthen     |	str_seq QSTR
4028d298c9fSsthen     {
4038d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $2.str, $2.len), 0);
4048d298c9fSsthen     }
4058d298c9fSsthen     |	str_seq QSTR unquoted_dotted_str
4068d298c9fSsthen     {
4078d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $2.str, $2.len), 0);
4088d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $3.str, $3.len), 0);
4098d298c9fSsthen     }
4108d298c9fSsthen     |	str_seq sp unquoted_dotted_str
41162ac0c33Sjakob     {
4129c620270Ssthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $3.str, $3.len), 0);
41362ac0c33Sjakob     }
4148d298c9fSsthen     |	str_seq sp QSTR
4158d298c9fSsthen     {
4168d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $3.str, $3.len), 0);
4178d298c9fSsthen     }
4188d298c9fSsthen     |	str_seq sp QSTR unquoted_dotted_str
4198d298c9fSsthen     {
4208d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $3.str, $3.len), 0);
4218d298c9fSsthen 	    zadd_rdata_txt_wireformat(zparser_conv_text(parser->rr_region, $4.str, $4.len), 0);
4228d298c9fSsthen     }
42362ac0c33Sjakob     ;
42462ac0c33Sjakob 
42562ac0c33Sjakob /*
42662ac0c33Sjakob  * Generate a single string from multiple STR tokens, separated by
42762ac0c33Sjakob  * spaces or dots.
42862ac0c33Sjakob  */
4298d298c9fSsthen concatenated_str_seq:	str
43062ac0c33Sjakob     |	'.'
43162ac0c33Sjakob     {
43262ac0c33Sjakob 	    $$.len = 1;
43362ac0c33Sjakob 	    $$.str = region_strdup(parser->rr_region, ".");
43462ac0c33Sjakob     }
4358d298c9fSsthen     |	concatenated_str_seq sp str
43662ac0c33Sjakob     {
43762ac0c33Sjakob 	    $$.len = $1.len + $3.len + 1;
43862ac0c33Sjakob 	    $$.str = (char *) region_alloc(parser->rr_region, $$.len + 1);
43962ac0c33Sjakob 	    memcpy($$.str, $1.str, $1.len);
44062ac0c33Sjakob 	    memcpy($$.str + $1.len, " ", 1);
44162ac0c33Sjakob 	    memcpy($$.str + $1.len + 1, $3.str, $3.len);
44262ac0c33Sjakob 	    $$.str[$$.len] = '\0';
44362ac0c33Sjakob     }
4448d298c9fSsthen     |	concatenated_str_seq '.' str
44562ac0c33Sjakob     {
44662ac0c33Sjakob 	    $$.len = $1.len + $3.len + 1;
44762ac0c33Sjakob 	    $$.str = (char *) region_alloc(parser->rr_region, $$.len + 1);
44862ac0c33Sjakob 	    memcpy($$.str, $1.str, $1.len);
44962ac0c33Sjakob 	    memcpy($$.str + $1.len, ".", 1);
45062ac0c33Sjakob 	    memcpy($$.str + $1.len + 1, $3.str, $3.len);
45162ac0c33Sjakob 	    $$.str[$$.len] = '\0';
45262ac0c33Sjakob     }
45362ac0c33Sjakob     ;
45462ac0c33Sjakob 
45562ac0c33Sjakob /* used to convert a nxt list of types */
4568d298c9fSsthen nxt_seq:	str
45762ac0c33Sjakob     {
45862ac0c33Sjakob 	    uint16_t type = rrtype_from_string($1.str);
45962ac0c33Sjakob 	    if (type != 0 && type < 128) {
46062ac0c33Sjakob 		    set_bit(nxtbits, type);
46162ac0c33Sjakob 	    } else {
46262ac0c33Sjakob 		    zc_error("bad type %d in NXT record", (int) type);
46362ac0c33Sjakob 	    }
46462ac0c33Sjakob     }
4658d298c9fSsthen     |	nxt_seq sp str
46662ac0c33Sjakob     {
46762ac0c33Sjakob 	    uint16_t type = rrtype_from_string($3.str);
46862ac0c33Sjakob 	    if (type != 0 && type < 128) {
46962ac0c33Sjakob 		    set_bit(nxtbits, type);
47062ac0c33Sjakob 	    } else {
47162ac0c33Sjakob 		    zc_error("bad type %d in NXT record", (int) type);
47262ac0c33Sjakob 	    }
47362ac0c33Sjakob     }
47462ac0c33Sjakob     ;
47562ac0c33Sjakob 
47662ac0c33Sjakob nsec_more:	SP nsec_more
47762ac0c33Sjakob     {
47862ac0c33Sjakob     }
47962ac0c33Sjakob     |	NL
48062ac0c33Sjakob     {
48162ac0c33Sjakob     }
4828d298c9fSsthen     |	str nsec_seq
48362ac0c33Sjakob     {
48462ac0c33Sjakob 	    uint16_t type = rrtype_from_string($1.str);
48562ac0c33Sjakob 	    if (type != 0) {
48662ac0c33Sjakob                     if (type > nsec_highest_rcode) {
48762ac0c33Sjakob                             nsec_highest_rcode = type;
48862ac0c33Sjakob                     }
48962ac0c33Sjakob 		    set_bitnsec(nsecbits, type);
49062ac0c33Sjakob 	    } else {
49162ac0c33Sjakob 		    zc_error("bad type %d in NSEC record", (int) type);
49262ac0c33Sjakob 	    }
49362ac0c33Sjakob     }
49462ac0c33Sjakob     ;
49562ac0c33Sjakob 
49662ac0c33Sjakob nsec_seq:	NL
49762ac0c33Sjakob 	|	SP nsec_more
49862ac0c33Sjakob 	;
49962ac0c33Sjakob 
50062ac0c33Sjakob /*
50162ac0c33Sjakob  * Sequence of STR tokens separated by spaces.	The spaces are not
50262ac0c33Sjakob  * preserved during concatenation.
50362ac0c33Sjakob  */
5048d298c9fSsthen str_sp_seq:	str
5058d298c9fSsthen     |	str_sp_seq sp str
50662ac0c33Sjakob     {
50762ac0c33Sjakob 	    char *result = (char *) region_alloc(parser->rr_region,
50862ac0c33Sjakob 						 $1.len + $3.len + 1);
50962ac0c33Sjakob 	    memcpy(result, $1.str, $1.len);
51062ac0c33Sjakob 	    memcpy(result + $1.len, $3.str, $3.len);
51162ac0c33Sjakob 	    $$.str = result;
51262ac0c33Sjakob 	    $$.len = $1.len + $3.len;
51362ac0c33Sjakob 	    $$.str[$$.len] = '\0';
51462ac0c33Sjakob     }
51562ac0c33Sjakob     ;
51662ac0c33Sjakob 
51762ac0c33Sjakob /*
51862ac0c33Sjakob  * Sequence of STR tokens separated by dots.  The dots are not
51962ac0c33Sjakob  * preserved during concatenation.
52062ac0c33Sjakob  */
5218d298c9fSsthen str_dot_seq:	str
5228d298c9fSsthen     |	str_dot_seq '.' str
52362ac0c33Sjakob     {
52462ac0c33Sjakob 	    char *result = (char *) region_alloc(parser->rr_region,
52562ac0c33Sjakob 						 $1.len + $3.len + 1);
52662ac0c33Sjakob 	    memcpy(result, $1.str, $1.len);
52762ac0c33Sjakob 	    memcpy(result + $1.len, $3.str, $3.len);
52862ac0c33Sjakob 	    $$.str = result;
52962ac0c33Sjakob 	    $$.len = $1.len + $3.len;
53062ac0c33Sjakob 	    $$.str[$$.len] = '\0';
53162ac0c33Sjakob     }
53262ac0c33Sjakob     ;
53362ac0c33Sjakob 
53462ac0c33Sjakob /*
53562ac0c33Sjakob  * A string that can contain dots.
53662ac0c33Sjakob  */
5378d298c9fSsthen unquoted_dotted_str:	STR
53862ac0c33Sjakob     |	'.'
53962ac0c33Sjakob     {
54062ac0c33Sjakob 	$$.str = ".";
54162ac0c33Sjakob 	$$.len = 1;
54262ac0c33Sjakob     }
5438d298c9fSsthen     |	unquoted_dotted_str '.'
54462ac0c33Sjakob     {
54562ac0c33Sjakob 	    char *result = (char *) region_alloc(parser->rr_region,
54662ac0c33Sjakob 						 $1.len + 2);
54762ac0c33Sjakob 	    memcpy(result, $1.str, $1.len);
54862ac0c33Sjakob 	    result[$1.len] = '.';
54962ac0c33Sjakob 	    $$.str = result;
55062ac0c33Sjakob 	    $$.len = $1.len + 1;
55162ac0c33Sjakob 	    $$.str[$$.len] = '\0';
55262ac0c33Sjakob     }
5538d298c9fSsthen     |	unquoted_dotted_str '.' STR
55462ac0c33Sjakob     {
55562ac0c33Sjakob 	    char *result = (char *) region_alloc(parser->rr_region,
55662ac0c33Sjakob 						 $1.len + $3.len + 2);
55762ac0c33Sjakob 	    memcpy(result, $1.str, $1.len);
55862ac0c33Sjakob 	    result[$1.len] = '.';
55962ac0c33Sjakob 	    memcpy(result + $1.len + 1, $3.str, $3.len);
56062ac0c33Sjakob 	    $$.str = result;
56162ac0c33Sjakob 	    $$.len = $1.len + $3.len + 1;
56262ac0c33Sjakob 	    $$.str[$$.len] = '\0';
56362ac0c33Sjakob     }
56462ac0c33Sjakob     ;
56562ac0c33Sjakob 
5668d298c9fSsthen /*
5678d298c9fSsthen  * A string that can contain dots or a quoted string.
5688d298c9fSsthen  */
5698d298c9fSsthen dotted_str:	unquoted_dotted_str | QSTR
5708d298c9fSsthen 
57162ac0c33Sjakob /* define what we can parse */
57262ac0c33Sjakob type_and_rdata:
57362ac0c33Sjakob     /*
57462ac0c33Sjakob      * All supported RR types.	We don't support NULL and types marked obsolete.
57562ac0c33Sjakob      */
57662ac0c33Sjakob     	T_A sp rdata_a
57762ac0c33Sjakob     |	T_A sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
57862ac0c33Sjakob     |	T_NS sp rdata_domain_name
57962ac0c33Sjakob     |	T_NS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
58062ac0c33Sjakob     |	T_MD sp rdata_domain_name { zc_warning_prev_line("MD is obsolete"); }
58162ac0c33Sjakob     |	T_MD sp rdata_unknown
58262ac0c33Sjakob     {
58362ac0c33Sjakob 	    zc_warning_prev_line("MD is obsolete");
58462ac0c33Sjakob 	    $$ = $1; parse_unknown_rdata($1, $3);
58562ac0c33Sjakob     }
58662ac0c33Sjakob     |	T_MF sp rdata_domain_name { zc_warning_prev_line("MF is obsolete"); }
58762ac0c33Sjakob     |	T_MF sp rdata_unknown
58862ac0c33Sjakob     {
58962ac0c33Sjakob 	    zc_warning_prev_line("MF is obsolete");
59062ac0c33Sjakob 	    $$ = $1;
59162ac0c33Sjakob 	    parse_unknown_rdata($1, $3);
59262ac0c33Sjakob     }
59362ac0c33Sjakob     |	T_CNAME sp rdata_domain_name
59462ac0c33Sjakob     |	T_CNAME sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
59562ac0c33Sjakob     |	T_SOA sp rdata_soa
59662ac0c33Sjakob     |	T_SOA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
59762ac0c33Sjakob     |	T_MB sp rdata_domain_name { zc_warning_prev_line("MB is obsolete"); }
59862ac0c33Sjakob     |	T_MB sp rdata_unknown
59962ac0c33Sjakob     {
60062ac0c33Sjakob 	    zc_warning_prev_line("MB is obsolete");
60162ac0c33Sjakob 	    $$ = $1;
60262ac0c33Sjakob 	    parse_unknown_rdata($1, $3);
60362ac0c33Sjakob     }
60462ac0c33Sjakob     |	T_MG sp rdata_domain_name
60562ac0c33Sjakob     |	T_MG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
60662ac0c33Sjakob     |	T_MR sp rdata_domain_name
60762ac0c33Sjakob     |	T_MR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
60862ac0c33Sjakob       /* NULL */
60962ac0c33Sjakob     |	T_WKS sp rdata_wks
61062ac0c33Sjakob     |	T_WKS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
61162ac0c33Sjakob     |	T_PTR sp rdata_domain_name
61262ac0c33Sjakob     |	T_PTR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
61362ac0c33Sjakob     |	T_HINFO sp rdata_hinfo
61462ac0c33Sjakob     |	T_HINFO sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
61562ac0c33Sjakob     |	T_MINFO sp rdata_minfo /* Experimental */
61662ac0c33Sjakob     |	T_MINFO sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
61762ac0c33Sjakob     |	T_MX sp rdata_mx
61862ac0c33Sjakob     |	T_MX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
61962ac0c33Sjakob     |	T_TXT sp rdata_txt
62062ac0c33Sjakob     |	T_TXT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
62162ac0c33Sjakob     |	T_SPF sp rdata_txt
62262ac0c33Sjakob     |	T_SPF sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
623d15afefcSflorian     |	T_AVC sp rdata_txt
624d15afefcSflorian     |	T_AVC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
62562ac0c33Sjakob     |	T_RP sp rdata_rp		/* RFC 1183 */
62662ac0c33Sjakob     |	T_RP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
62762ac0c33Sjakob     |	T_AFSDB sp rdata_afsdb	/* RFC 1183 */
62862ac0c33Sjakob     |	T_AFSDB sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
62962ac0c33Sjakob     |	T_X25 sp rdata_x25	/* RFC 1183 */
63062ac0c33Sjakob     |	T_X25 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
63162ac0c33Sjakob     |	T_ISDN sp rdata_isdn	/* RFC 1183 */
63262ac0c33Sjakob     |	T_ISDN sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
63362ac0c33Sjakob     |	T_IPSECKEY sp rdata_ipseckey	/* RFC 4025 */
63462ac0c33Sjakob     |	T_IPSECKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
63562ac0c33Sjakob     |	T_DHCID sp rdata_dhcid
63662ac0c33Sjakob     |	T_DHCID sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
63762ac0c33Sjakob     |	T_RT sp rdata_rt		/* RFC 1183 */
63862ac0c33Sjakob     |	T_RT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
63962ac0c33Sjakob     |	T_NSAP sp rdata_nsap	/* RFC 1706 */
64062ac0c33Sjakob     |	T_NSAP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
64162ac0c33Sjakob     |	T_SIG sp rdata_rrsig
64262ac0c33Sjakob     |	T_SIG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
64362ac0c33Sjakob     |	T_KEY sp rdata_dnskey
64462ac0c33Sjakob     |	T_KEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
64562ac0c33Sjakob     |	T_PX sp rdata_px		/* RFC 2163 */
64662ac0c33Sjakob     |	T_PX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
64762ac0c33Sjakob     |	T_AAAA sp rdata_aaaa
64862ac0c33Sjakob     |	T_AAAA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
64962ac0c33Sjakob     |	T_LOC sp rdata_loc
65062ac0c33Sjakob     |	T_LOC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
65162ac0c33Sjakob     |	T_NXT sp rdata_nxt
65262ac0c33Sjakob     |	T_NXT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
65362ac0c33Sjakob     |	T_SRV sp rdata_srv
65462ac0c33Sjakob     |	T_SRV sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
65562ac0c33Sjakob     |	T_NAPTR sp rdata_naptr	/* RFC 2915 */
65662ac0c33Sjakob     |	T_NAPTR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
65762ac0c33Sjakob     |	T_KX sp rdata_kx		/* RFC 2230 */
65862ac0c33Sjakob     |	T_KX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
65962ac0c33Sjakob     |	T_CERT sp rdata_cert	/* RFC 2538 */
66062ac0c33Sjakob     |	T_CERT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
66162ac0c33Sjakob     |	T_DNAME sp rdata_domain_name /* RFC 2672 */
66262ac0c33Sjakob     |	T_DNAME sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
66362ac0c33Sjakob     |	T_APL trail		/* RFC 3123 */
66462ac0c33Sjakob     |	T_APL sp rdata_apl	/* RFC 3123 */
66562ac0c33Sjakob     |	T_APL sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
66662ac0c33Sjakob     |	T_DS sp rdata_ds
66762ac0c33Sjakob     |	T_DS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
66862ac0c33Sjakob     |	T_DLV sp rdata_dlv { if (dlv_warn) { dlv_warn = 0; zc_warning_prev_line("DLV is experimental"); } }
66962ac0c33Sjakob     |	T_DLV sp rdata_unknown { if (dlv_warn) { dlv_warn = 0; zc_warning_prev_line("DLV is experimental"); } $$ = $1; parse_unknown_rdata($1, $3); }
67062ac0c33Sjakob     |	T_SSHFP sp rdata_sshfp
671eab1363eSsthen     |	T_SSHFP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); check_sshfp(); }
67262ac0c33Sjakob     |	T_RRSIG sp rdata_rrsig
67362ac0c33Sjakob     |	T_RRSIG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
67462ac0c33Sjakob     |	T_NSEC sp rdata_nsec
67562ac0c33Sjakob     |	T_NSEC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
67662ac0c33Sjakob     |	T_NSEC3 sp rdata_nsec3
67762ac0c33Sjakob     |	T_NSEC3 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
67862ac0c33Sjakob     |	T_NSEC3PARAM sp rdata_nsec3_param
67962ac0c33Sjakob     |	T_NSEC3PARAM sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
68062ac0c33Sjakob     |	T_DNSKEY sp rdata_dnskey
68162ac0c33Sjakob     |	T_DNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
682d11a62c8Ssthen     |	T_TLSA sp rdata_tlsa
683d11a62c8Ssthen     |	T_TLSA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
68418e77612Sflorian     |	T_SMIMEA sp rdata_smimea
68518e77612Sflorian     |	T_SMIMEA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
68675343be4Ssthen     |	T_NID sp rdata_nid
68775343be4Ssthen     |	T_NID sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
68875343be4Ssthen     |	T_L32 sp rdata_l32
68975343be4Ssthen     |	T_L32 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
69075343be4Ssthen     |	T_L64 sp rdata_l64
69175343be4Ssthen     |	T_L64 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
69275343be4Ssthen     |	T_LP sp rdata_lp
69375343be4Ssthen     |	T_LP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
6949c620270Ssthen     |	T_EUI48 sp rdata_eui48
6959c620270Ssthen     |	T_EUI48 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
6969c620270Ssthen     |	T_EUI64 sp rdata_eui64
6979c620270Ssthen     |	T_EUI64 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
698a302926fSbrad     |	T_CAA sp rdata_caa
699a302926fSbrad     |	T_CAA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
70003739794Sbrad     |	T_CDS sp rdata_ds
70103739794Sbrad     |	T_CDS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
70203739794Sbrad     |	T_CDNSKEY sp rdata_dnskey
70303739794Sbrad     |	T_CDNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
704c1e73312Sflorian     |	T_OPENPGPKEY sp rdata_openpgpkey
705c1e73312Sflorian     |	T_OPENPGPKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
706275a8d89Sflorian     |	T_CSYNC sp rdata_csync
707275a8d89Sflorian     |	T_CSYNC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
708977db6e5Sflorian     |	T_ZONEMD sp rdata_zonemd
709977db6e5Sflorian     |	T_ZONEMD sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
710*063644e9Sflorian     |	T_SVCB sp rdata_svcb
711*063644e9Sflorian     |	T_SVCB sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
712*063644e9Sflorian     |	T_HTTPS sp rdata_svcb
713*063644e9Sflorian     |	T_HTTPS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
714e3d8a0a5Ssthen     |	T_URI sp rdata_uri
715e3d8a0a5Ssthen     |	T_URI sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
71662ac0c33Sjakob     |	T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
7178d298c9fSsthen     |	str error NL
71862ac0c33Sjakob     {
71962ac0c33Sjakob 	    zc_error_prev_line("unrecognized RR type '%s'", $1.str);
72062ac0c33Sjakob     }
72162ac0c33Sjakob     ;
72262ac0c33Sjakob 
72362ac0c33Sjakob /*
72462ac0c33Sjakob  *
72562ac0c33Sjakob  * below are all the definition for all the different rdata
72662ac0c33Sjakob  *
72762ac0c33Sjakob  */
72862ac0c33Sjakob 
72962ac0c33Sjakob rdata_a:	dotted_str trail
73062ac0c33Sjakob     {
73162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_a(parser->region, $1.str));
73262ac0c33Sjakob     }
73362ac0c33Sjakob     ;
73462ac0c33Sjakob 
73562ac0c33Sjakob rdata_domain_name:	dname trail
73662ac0c33Sjakob     {
73762ac0c33Sjakob 	    /* convert a single dname record */
73862ac0c33Sjakob 	    zadd_rdata_domain($1);
73962ac0c33Sjakob     }
74062ac0c33Sjakob     ;
74162ac0c33Sjakob 
7428d298c9fSsthen rdata_soa:	dname sp dname sp str sp str sp str sp str sp str trail
74362ac0c33Sjakob     {
74462ac0c33Sjakob 	    /* convert the soa data */
74562ac0c33Sjakob 	    zadd_rdata_domain($1);	/* prim. ns */
74662ac0c33Sjakob 	    zadd_rdata_domain($3);	/* email */
74762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_serial(parser->region, $5.str)); /* serial */
74862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_period(parser->region, $7.str)); /* refresh */
74962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_period(parser->region, $9.str)); /* retry */
75062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_period(parser->region, $11.str)); /* expire */
75162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_period(parser->region, $13.str)); /* minimum */
75262ac0c33Sjakob     }
75362ac0c33Sjakob     ;
75462ac0c33Sjakob 
7558d298c9fSsthen rdata_wks:	dotted_str sp str sp concatenated_str_seq trail
75662ac0c33Sjakob     {
75762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_a(parser->region, $1.str)); /* address */
75862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_services(parser->region, $3.str, $5.str)); /* protocol and services */
75962ac0c33Sjakob     }
76062ac0c33Sjakob     ;
76162ac0c33Sjakob 
7628d298c9fSsthen rdata_hinfo:	str sp str trail
76362ac0c33Sjakob     {
76462ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $1.str, $1.len)); /* CPU */
76562ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $3.str, $3.len)); /* OS*/
76662ac0c33Sjakob     }
76762ac0c33Sjakob     ;
76862ac0c33Sjakob 
76962ac0c33Sjakob rdata_minfo:	dname sp dname trail
77062ac0c33Sjakob     {
77162ac0c33Sjakob 	    /* convert a single dname record */
77262ac0c33Sjakob 	    zadd_rdata_domain($1);
77362ac0c33Sjakob 	    zadd_rdata_domain($3);
77462ac0c33Sjakob     }
77562ac0c33Sjakob     ;
77662ac0c33Sjakob 
7778d298c9fSsthen rdata_mx:	str sp dname trail
77862ac0c33Sjakob     {
77962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));  /* priority */
78062ac0c33Sjakob 	    zadd_rdata_domain($3);	/* MX host */
78162ac0c33Sjakob     }
78262ac0c33Sjakob     ;
78362ac0c33Sjakob 
78462ac0c33Sjakob rdata_txt:	str_seq trail
785f72b2965Sjakob     {
786f72b2965Sjakob 	zadd_rdata_txt_clean_wireformat();
787f72b2965Sjakob     }
78862ac0c33Sjakob     ;
78962ac0c33Sjakob 
79062ac0c33Sjakob /* RFC 1183 */
79162ac0c33Sjakob rdata_rp:	dname sp dname trail
79262ac0c33Sjakob     {
79362ac0c33Sjakob 	    zadd_rdata_domain($1); /* mbox d-name */
79462ac0c33Sjakob 	    zadd_rdata_domain($3); /* txt d-name */
79562ac0c33Sjakob     }
79662ac0c33Sjakob     ;
79762ac0c33Sjakob 
79862ac0c33Sjakob /* RFC 1183 */
7998d298c9fSsthen rdata_afsdb:	str sp dname trail
80062ac0c33Sjakob     {
80162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* subtype */
80262ac0c33Sjakob 	    zadd_rdata_domain($3); /* domain name */
80362ac0c33Sjakob     }
80462ac0c33Sjakob     ;
80562ac0c33Sjakob 
80662ac0c33Sjakob /* RFC 1183 */
8078d298c9fSsthen rdata_x25:	str trail
80862ac0c33Sjakob     {
80962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $1.str, $1.len)); /* X.25 address. */
81062ac0c33Sjakob     }
81162ac0c33Sjakob     ;
81262ac0c33Sjakob 
81362ac0c33Sjakob /* RFC 1183 */
8148d298c9fSsthen rdata_isdn:	str trail
81562ac0c33Sjakob     {
81662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $1.str, $1.len)); /* address */
81762ac0c33Sjakob     }
8188d298c9fSsthen     |	str sp str trail
81962ac0c33Sjakob     {
82062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $1.str, $1.len)); /* address */
82162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $3.str, $3.len)); /* sub-address */
82262ac0c33Sjakob     }
82362ac0c33Sjakob     ;
82462ac0c33Sjakob 
82562ac0c33Sjakob /* RFC 1183 */
8268d298c9fSsthen rdata_rt:	str sp dname trail
82762ac0c33Sjakob     {
82862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* preference */
82962ac0c33Sjakob 	    zadd_rdata_domain($3); /* intermediate host */
83062ac0c33Sjakob     }
83162ac0c33Sjakob     ;
83262ac0c33Sjakob 
83362ac0c33Sjakob /* RFC 1706 */
83462ac0c33Sjakob rdata_nsap:	str_dot_seq trail
83562ac0c33Sjakob     {
83662ac0c33Sjakob 	    /* String must start with "0x" or "0X".	 */
83762ac0c33Sjakob 	    if (strncasecmp($1.str, "0x", 2) != 0) {
83862ac0c33Sjakob 		    zc_error_prev_line("NSAP rdata must start with '0x'");
83962ac0c33Sjakob 	    } else {
84062ac0c33Sjakob 		    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $1.str + 2, $1.len - 2)); /* NSAP */
84162ac0c33Sjakob 	    }
84262ac0c33Sjakob     }
84362ac0c33Sjakob     ;
84462ac0c33Sjakob 
84562ac0c33Sjakob /* RFC 2163 */
8468d298c9fSsthen rdata_px:	str sp dname sp dname trail
84762ac0c33Sjakob     {
84862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* preference */
84962ac0c33Sjakob 	    zadd_rdata_domain($3); /* MAP822 */
85062ac0c33Sjakob 	    zadd_rdata_domain($5); /* MAPX400 */
85162ac0c33Sjakob     }
85262ac0c33Sjakob     ;
85362ac0c33Sjakob 
85462ac0c33Sjakob rdata_aaaa:	dotted_str trail
85562ac0c33Sjakob     {
85662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_aaaa(parser->region, $1.str));  /* IPv6 address */
85762ac0c33Sjakob     }
85862ac0c33Sjakob     ;
85962ac0c33Sjakob 
86062ac0c33Sjakob rdata_loc:	concatenated_str_seq trail
86162ac0c33Sjakob     {
86262ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_loc(parser->region, $1.str)); /* Location */
86362ac0c33Sjakob     }
86462ac0c33Sjakob     ;
86562ac0c33Sjakob 
86662ac0c33Sjakob rdata_nxt:	dname sp nxt_seq trail
86762ac0c33Sjakob     {
86862ac0c33Sjakob 	    zadd_rdata_domain($1); /* nxt name */
86962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_nxt(parser->region, nxtbits)); /* nxt bitlist */
87062ac0c33Sjakob 	    memset(nxtbits, 0, sizeof(nxtbits));
87162ac0c33Sjakob     }
87262ac0c33Sjakob     ;
87362ac0c33Sjakob 
8748d298c9fSsthen rdata_srv:	str sp str sp str sp dname trail
87562ac0c33Sjakob     {
87662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* prio */
87762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str)); /* weight */
87862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $5.str)); /* port */
87962ac0c33Sjakob 	    zadd_rdata_domain($7); /* target name */
88062ac0c33Sjakob     }
88162ac0c33Sjakob     ;
88262ac0c33Sjakob 
88362ac0c33Sjakob /* RFC 2915 */
8848d298c9fSsthen rdata_naptr:	str sp str sp str sp str sp str sp dname trail
88562ac0c33Sjakob     {
88662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* order */
88762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str)); /* preference */
88862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $5.str, $5.len)); /* flags */
88962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $7.str, $7.len)); /* service */
89062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_text(parser->region, $9.str, $9.len)); /* regexp */
89162ac0c33Sjakob 	    zadd_rdata_domain($11); /* target name */
89262ac0c33Sjakob     }
89362ac0c33Sjakob     ;
89462ac0c33Sjakob 
89562ac0c33Sjakob /* RFC 2230 */
8968d298c9fSsthen rdata_kx:	str sp dname trail
89762ac0c33Sjakob     {
89862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* preference */
89962ac0c33Sjakob 	    zadd_rdata_domain($3); /* exchanger */
90062ac0c33Sjakob     }
90162ac0c33Sjakob     ;
90262ac0c33Sjakob 
90362ac0c33Sjakob /* RFC 2538 */
9048d298c9fSsthen rdata_cert:	str sp str sp str sp str_sp_seq trail
90562ac0c33Sjakob     {
90662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_certificate_type(parser->region, $1.str)); /* type */
90762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str)); /* key tag */
90862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_algorithm(parser->region, $5.str)); /* algorithm */
90962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_b64(parser->region, $7.str)); /* certificate or CRL */
91062ac0c33Sjakob     }
91162ac0c33Sjakob     ;
91262ac0c33Sjakob 
91362ac0c33Sjakob /* RFC 3123 */
91462ac0c33Sjakob rdata_apl:	rdata_apl_seq trail
91562ac0c33Sjakob     ;
91662ac0c33Sjakob 
91762ac0c33Sjakob rdata_apl_seq:	dotted_str
91862ac0c33Sjakob     {
91962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_apl_rdata(parser->region, $1.str));
92062ac0c33Sjakob     }
92162ac0c33Sjakob     |	rdata_apl_seq sp dotted_str
92262ac0c33Sjakob     {
92362ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_apl_rdata(parser->region, $3.str));
92462ac0c33Sjakob     }
92562ac0c33Sjakob     ;
92662ac0c33Sjakob 
9278d298c9fSsthen rdata_ds:	str sp str sp str sp str_sp_seq trail
92862ac0c33Sjakob     {
92962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* keytag */
93062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_algorithm(parser->region, $3.str)); /* alg */
93162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* type */
93262ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len)); /* hash */
93362ac0c33Sjakob     }
93462ac0c33Sjakob     ;
93562ac0c33Sjakob 
9368d298c9fSsthen rdata_dlv:	str sp str sp str sp str_sp_seq trail
93762ac0c33Sjakob     {
93862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* keytag */
93962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_algorithm(parser->region, $3.str)); /* alg */
94062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* type */
94162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len)); /* hash */
94262ac0c33Sjakob     }
94362ac0c33Sjakob     ;
94462ac0c33Sjakob 
9458d298c9fSsthen rdata_sshfp:	str sp str sp str_sp_seq trail
94662ac0c33Sjakob     {
94762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); /* alg */
94862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* fp type */
94962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $5.str, $5.len)); /* hash */
950eab1363eSsthen 	    check_sshfp();
95162ac0c33Sjakob     }
95262ac0c33Sjakob     ;
95362ac0c33Sjakob 
95462ac0c33Sjakob rdata_dhcid:	str_sp_seq trail
95562ac0c33Sjakob     {
95662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_b64(parser->region, $1.str)); /* data blob */
95762ac0c33Sjakob     }
95862ac0c33Sjakob     ;
95962ac0c33Sjakob 
9608d298c9fSsthen rdata_rrsig:	str sp str sp str sp str sp str sp str sp str sp wire_dname sp str_sp_seq trail
96162ac0c33Sjakob     {
96262ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_rrtype(parser->region, $1.str)); /* rr covered */
96362ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_algorithm(parser->region, $3.str)); /* alg */
96462ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* # labels */
96562ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_period(parser->region, $7.str)); /* # orig TTL */
96662ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_time(parser->region, $9.str)); /* sig exp */
96762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_time(parser->region, $11.str)); /* sig inc */
96862ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $13.str)); /* key id */
96962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_dns_name(parser->region,
97062ac0c33Sjakob 				(const uint8_t*) $15.str,$15.len)); /* sig name */
97162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_b64(parser->region, $17.str)); /* sig data */
97262ac0c33Sjakob     }
97362ac0c33Sjakob     ;
97462ac0c33Sjakob 
97562ac0c33Sjakob rdata_nsec:	wire_dname nsec_seq
97662ac0c33Sjakob     {
97762ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_dns_name(parser->region,
97862ac0c33Sjakob 				(const uint8_t*) $1.str, $1.len)); /* nsec name */
97962ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_nsec(parser->region, nsecbits)); /* nsec bitlist */
98062ac0c33Sjakob 	    memset(nsecbits, 0, sizeof(nsecbits));
98162ac0c33Sjakob             nsec_highest_rcode = 0;
98262ac0c33Sjakob     }
98362ac0c33Sjakob     ;
98462ac0c33Sjakob 
9858d298c9fSsthen rdata_nsec3:   str sp str sp str sp str sp str nsec_seq
98662ac0c33Sjakob     {
98762ac0c33Sjakob #ifdef NSEC3
98862ac0c33Sjakob 	    nsec3_add_params($1.str, $3.str, $5.str, $7.str, $7.len);
98962ac0c33Sjakob 
99062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_b32(parser->region, $9.str)); /* next hashed name */
99162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_nsec(parser->region, nsecbits)); /* nsec bitlist */
99262ac0c33Sjakob 	    memset(nsecbits, 0, sizeof(nsecbits));
99362ac0c33Sjakob 	    nsec_highest_rcode = 0;
99462ac0c33Sjakob #else
99562ac0c33Sjakob 	    zc_error_prev_line("nsec3 not supported");
99662ac0c33Sjakob #endif /* NSEC3 */
99762ac0c33Sjakob     }
99862ac0c33Sjakob     ;
99962ac0c33Sjakob 
10008d298c9fSsthen rdata_nsec3_param:   str sp str sp str sp str trail
100162ac0c33Sjakob     {
100262ac0c33Sjakob #ifdef NSEC3
100362ac0c33Sjakob 	    nsec3_add_params($1.str, $3.str, $5.str, $7.str, $7.len);
100462ac0c33Sjakob #else
100562ac0c33Sjakob 	    zc_error_prev_line("nsec3 not supported");
100662ac0c33Sjakob #endif /* NSEC3 */
100762ac0c33Sjakob     }
100862ac0c33Sjakob     ;
100962ac0c33Sjakob 
10108d298c9fSsthen rdata_tlsa:	str sp str sp str sp str_sp_seq trail
1011d11a62c8Ssthen     {
1012d11a62c8Ssthen 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); /* usage */
1013d11a62c8Ssthen 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* selector */
1014d11a62c8Ssthen 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* matching type */
1015d11a62c8Ssthen 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len)); /* ca data */
1016d11a62c8Ssthen     }
1017d11a62c8Ssthen     ;
1018d11a62c8Ssthen 
10198d298c9fSsthen rdata_smimea:	str sp str sp str sp str_sp_seq trail
102018e77612Sflorian     {
102118e77612Sflorian 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); /* usage */
102218e77612Sflorian 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* selector */
102318e77612Sflorian 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* matching type */
102418e77612Sflorian 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len)); /* ca data */
102518e77612Sflorian     }
102618e77612Sflorian     ;
102718e77612Sflorian 
10288d298c9fSsthen rdata_dnskey:	str sp str sp str sp str_sp_seq trail
102962ac0c33Sjakob     {
103062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* flags */
103162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* proto */
103262ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_algorithm(parser->region, $5.str)); /* alg */
103362ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_b64(parser->region, $7.str)); /* hash */
103462ac0c33Sjakob     }
103562ac0c33Sjakob     ;
103662ac0c33Sjakob 
10378d298c9fSsthen rdata_ipsec_base: str sp str sp str sp dotted_str
103862ac0c33Sjakob     {
103962ac0c33Sjakob 	    const dname_type* name = 0;
104062ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); /* precedence */
104162ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* gateway type */
104262ac0c33Sjakob 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* algorithm */
104362ac0c33Sjakob 	    switch(atoi($3.str)) {
104462ac0c33Sjakob 		case IPSECKEY_NOGATEWAY:
104562ac0c33Sjakob 			zadd_rdata_wireformat(alloc_rdata_init(parser->region, "", 0));
104662ac0c33Sjakob 			break;
104762ac0c33Sjakob 		case IPSECKEY_IP4:
104862ac0c33Sjakob 			zadd_rdata_wireformat(zparser_conv_a(parser->region, $7.str));
104962ac0c33Sjakob 			break;
105062ac0c33Sjakob 		case IPSECKEY_IP6:
105162ac0c33Sjakob 			zadd_rdata_wireformat(zparser_conv_aaaa(parser->region, $7.str));
105262ac0c33Sjakob 			break;
105362ac0c33Sjakob 		case IPSECKEY_DNAME:
105462ac0c33Sjakob 			/* convert and insert the dname */
105562ac0c33Sjakob 			if(strlen($7.str) == 0)
105662ac0c33Sjakob 				zc_error_prev_line("IPSECKEY must specify gateway name");
10574b6a9f59Sflorian 			if(!(name = dname_parse(parser->region, $7.str))) {
105862ac0c33Sjakob 				zc_error_prev_line("IPSECKEY bad gateway dname %s", $7.str);
10594b6a9f59Sflorian 				break;
10604b6a9f59Sflorian 			}
10618d8f1862Ssthen 			if($7.str[strlen($7.str)-1] != '.') {
10628d8f1862Ssthen 				if(parser->origin == error_domain) {
10638d8f1862Ssthen 		    			zc_error("cannot concatenate origin to domain name, because origin failed to parse");
10648d8f1862Ssthen 					break;
1065eab1363eSsthen 				} else if(name->name_size + domain_dname(parser->origin)->name_size - 1 > MAXDOMAINLEN) {
1066eab1363eSsthen 					zc_error("ipsec gateway name exceeds %d character limit",
1067eab1363eSsthen 						MAXDOMAINLEN);
1068eab1363eSsthen 					break;
10698d8f1862Ssthen 				}
107062ac0c33Sjakob 				name = dname_concatenate(parser->rr_region, name,
107162ac0c33Sjakob 					domain_dname(parser->origin));
10728d8f1862Ssthen 			}
107362ac0c33Sjakob 			zadd_rdata_wireformat(alloc_rdata_init(parser->region,
107462ac0c33Sjakob 				dname_name(name), name->name_size));
107562ac0c33Sjakob 			break;
107662ac0c33Sjakob 		default:
107762ac0c33Sjakob 			zc_error_prev_line("unknown IPSECKEY gateway type");
107862ac0c33Sjakob 	    }
107962ac0c33Sjakob     }
108062ac0c33Sjakob     ;
108162ac0c33Sjakob 
108262ac0c33Sjakob rdata_ipseckey:	rdata_ipsec_base sp str_sp_seq trail
108362ac0c33Sjakob     {
108462ac0c33Sjakob 	   zadd_rdata_wireformat(zparser_conv_b64(parser->region, $3.str)); /* public key */
108562ac0c33Sjakob     }
108662ac0c33Sjakob     | rdata_ipsec_base trail
108762ac0c33Sjakob     ;
108862ac0c33Sjakob 
108975343be4Ssthen /* RFC 6742 */
10908d298c9fSsthen rdata_nid:	str sp dotted_str trail
109175343be4Ssthen     {
109275343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));  /* preference */
109375343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_ilnp64(parser->region, $3.str));  /* NodeID */
109475343be4Ssthen     }
109575343be4Ssthen     ;
109675343be4Ssthen 
10978d298c9fSsthen rdata_l32:	str sp dotted_str trail
109875343be4Ssthen     {
109975343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));  /* preference */
110075343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_a(parser->region, $3.str));  /* Locator32 */
110175343be4Ssthen     }
110275343be4Ssthen     ;
110375343be4Ssthen 
11048d298c9fSsthen rdata_l64:	str sp dotted_str trail
110575343be4Ssthen     {
110675343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));  /* preference */
110775343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_ilnp64(parser->region, $3.str));  /* Locator64 */
110875343be4Ssthen     }
110975343be4Ssthen     ;
111075343be4Ssthen 
11118d298c9fSsthen rdata_lp:	str sp dname trail
111275343be4Ssthen     {
111375343be4Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));  /* preference */
111475343be4Ssthen 	    zadd_rdata_domain($3);  /* FQDN */
111575343be4Ssthen     }
111675343be4Ssthen     ;
111775343be4Ssthen 
11188d298c9fSsthen rdata_eui48:	str trail
11199c620270Ssthen     {
11209c620270Ssthen 	    zadd_rdata_wireformat(zparser_conv_eui(parser->region, $1.str, 48));
11219c620270Ssthen     }
11229c620270Ssthen     ;
11239c620270Ssthen 
11248d298c9fSsthen rdata_eui64:	str trail
11259c620270Ssthen     {
11269c620270Ssthen 	    zadd_rdata_wireformat(zparser_conv_eui(parser->region, $1.str, 64));
1127a302926fSbrad     }
1128a302926fSbrad     ;
1129a302926fSbrad 
1130e3d8a0a5Ssthen /* RFC7553 */
11318d298c9fSsthen rdata_uri:	str sp str sp dotted_str trail
1132e3d8a0a5Ssthen     {
1133e3d8a0a5Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str)); /* priority */
1134e3d8a0a5Ssthen 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str)); /* weight */
1135e3d8a0a5Ssthen 	    zadd_rdata_wireformat(zparser_conv_long_text(parser->region, $5.str, $5.len)); /* target */
1136e3d8a0a5Ssthen     }
1137e3d8a0a5Ssthen     ;
1138e3d8a0a5Ssthen 
1139a302926fSbrad /* RFC 6844 */
11408d298c9fSsthen rdata_caa:	str sp str sp dotted_str trail
1141a302926fSbrad     {
1142a302926fSbrad 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str)); /* Flags */
1143a302926fSbrad 	    zadd_rdata_wireformat(zparser_conv_tag(parser->region, $3.str, $3.len)); /* Tag */
1144a302926fSbrad 	    zadd_rdata_wireformat(zparser_conv_long_text(parser->region, $5.str, $5.len)); /* Value */
11459c620270Ssthen     }
11469c620270Ssthen     ;
11479c620270Ssthen 
1148c1e73312Sflorian /* RFC7929 */
1149c1e73312Sflorian rdata_openpgpkey:	str_sp_seq trail
1150c1e73312Sflorian     {
1151c1e73312Sflorian 	    zadd_rdata_wireformat(zparser_conv_b64(parser->region, $1.str));
1152c1e73312Sflorian     }
1153c1e73312Sflorian     ;
1154c1e73312Sflorian 
1155275a8d89Sflorian /* RFC7477 */
11568d298c9fSsthen rdata_csync:	str sp str nsec_seq
1157275a8d89Sflorian     {
1158275a8d89Sflorian 	    zadd_rdata_wireformat(zparser_conv_serial(parser->region, $1.str));
1159275a8d89Sflorian 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str));
1160275a8d89Sflorian 	    zadd_rdata_wireformat(zparser_conv_nsec(parser->region, nsecbits)); /* nsec bitlist */
1161275a8d89Sflorian 	    memset(nsecbits, 0, sizeof(nsecbits));
1162275a8d89Sflorian             nsec_highest_rcode = 0;
1163275a8d89Sflorian     }
1164275a8d89Sflorian     ;
1165275a8d89Sflorian 
1166977db6e5Sflorian /* draft-ietf-dnsop-dns-zone-digest */
11678d298c9fSsthen rdata_zonemd:	str sp str sp str sp str_sp_seq trail
1168977db6e5Sflorian     {
1169977db6e5Sflorian 	    zadd_rdata_wireformat(zparser_conv_serial(parser->region, $1.str)); /* serial */
1170977db6e5Sflorian 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str)); /* scheme */
1171977db6e5Sflorian 	    zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str)); /* hash algorithm */
1172977db6e5Sflorian 	    zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len)); /* digest */
1173977db6e5Sflorian     }
1174977db6e5Sflorian     ;
1175977db6e5Sflorian 
1176*063644e9Sflorian svcparam:	dotted_str QSTR
1177*063644e9Sflorian     {
1178*063644e9Sflorian 	zadd_rdata_wireformat(zparser_conv_svcbparam(
1179*063644e9Sflorian 		parser->region, $1.str, $1.len, $2.str, $2.len));
1180*063644e9Sflorian     }
1181*063644e9Sflorian     |		dotted_str
1182*063644e9Sflorian     {
1183*063644e9Sflorian 	zadd_rdata_wireformat(zparser_conv_svcbparam(
1184*063644e9Sflorian 		parser->region, $1.str, $1.len, NULL, 0));
1185*063644e9Sflorian     }
1186*063644e9Sflorian     ;
1187*063644e9Sflorian svcparams:	svcparam
1188*063644e9Sflorian     |		svcparams sp svcparam
1189*063644e9Sflorian     ;
1190*063644e9Sflorian /* draft-ietf-dnsop-svcb-https */
1191*063644e9Sflorian rdata_svcb_base:	str sp dname
1192*063644e9Sflorian     {
1193*063644e9Sflorian 	    /* SvcFieldPriority */
1194*063644e9Sflorian 	    zadd_rdata_wireformat(zparser_conv_short(parser->region, $1.str));
1195*063644e9Sflorian 	    /* SvcDomainName */
1196*063644e9Sflorian 	    zadd_rdata_domain($3);
1197*063644e9Sflorian     };
1198*063644e9Sflorian rdata_svcb:     rdata_svcb_base sp svcparams trail
1199*063644e9Sflorian     {
1200*063644e9Sflorian         zadd_rdata_svcb_check_wireformat();
1201*063644e9Sflorian     }
1202*063644e9Sflorian     |   rdata_svcb_base trail
1203*063644e9Sflorian     ;
1204*063644e9Sflorian 
12058d298c9fSsthen rdata_unknown:	URR sp str sp str_sp_seq trail
120662ac0c33Sjakob     {
12072fd875a4Ssthen 	    /* $2 is the number of octets, currently ignored */
1208b90bb40eSsthen 	    $$ = zparser_conv_hex(parser->rr_region, $5.str, $5.len);
120962ac0c33Sjakob 
121062ac0c33Sjakob     }
12118d298c9fSsthen     |	URR sp str trail
121262ac0c33Sjakob     {
1213b90bb40eSsthen 	    $$ = zparser_conv_hex(parser->rr_region, "", 0);
121462ac0c33Sjakob     }
121562ac0c33Sjakob     |	URR error NL
121662ac0c33Sjakob     {
1217b90bb40eSsthen 	    $$ = zparser_conv_hex(parser->rr_region, "", 0);
121862ac0c33Sjakob     }
121962ac0c33Sjakob     ;
122062ac0c33Sjakob %%
122162ac0c33Sjakob 
122262ac0c33Sjakob int
122362ac0c33Sjakob yywrap(void)
122462ac0c33Sjakob {
122562ac0c33Sjakob 	return 1;
122662ac0c33Sjakob }
122762ac0c33Sjakob 
122862ac0c33Sjakob /*
122962ac0c33Sjakob  * Create the parser.
123062ac0c33Sjakob  */
123162ac0c33Sjakob zparser_type *
zparser_create(region_type * region,region_type * rr_region,namedb_type * db)123262ac0c33Sjakob zparser_create(region_type *region, region_type *rr_region, namedb_type *db)
123362ac0c33Sjakob {
123462ac0c33Sjakob 	zparser_type *result;
123562ac0c33Sjakob 
123662ac0c33Sjakob 	result = (zparser_type *) region_alloc(region, sizeof(zparser_type));
123762ac0c33Sjakob 	result->region = region;
123862ac0c33Sjakob 	result->rr_region = rr_region;
123962ac0c33Sjakob 	result->db = db;
124062ac0c33Sjakob 
124162ac0c33Sjakob 	result->filename = NULL;
124262ac0c33Sjakob 	result->current_zone = NULL;
124362ac0c33Sjakob 	result->origin = NULL;
124462ac0c33Sjakob 	result->prev_dname = NULL;
124562ac0c33Sjakob 
12468d8f1862Ssthen 	result->temporary_rdatas = (rdata_atom_type *) region_alloc_array(
12478d8f1862Ssthen 		result->region, MAXRDATALEN, sizeof(rdata_atom_type));
124862ac0c33Sjakob 
124962ac0c33Sjakob 	return result;
125062ac0c33Sjakob }
125162ac0c33Sjakob 
125262ac0c33Sjakob /*
125362ac0c33Sjakob  * Initialize the parser for a new zone file.
125462ac0c33Sjakob  */
125562ac0c33Sjakob void
zparser_init(const char * filename,uint32_t ttl,uint16_t klass,const dname_type * origin)125662ac0c33Sjakob zparser_init(const char *filename, uint32_t ttl, uint16_t klass,
125762ac0c33Sjakob 	     const dname_type *origin)
125862ac0c33Sjakob {
125962ac0c33Sjakob 	memset(nxtbits, 0, sizeof(nxtbits));
126062ac0c33Sjakob 	memset(nsecbits, 0, sizeof(nsecbits));
126162ac0c33Sjakob         nsec_highest_rcode = 0;
126262ac0c33Sjakob 
126362ac0c33Sjakob 	parser->default_ttl = ttl;
126462ac0c33Sjakob 	parser->default_class = klass;
126562ac0c33Sjakob 	parser->current_zone = NULL;
126662ac0c33Sjakob 	parser->origin = domain_table_insert(parser->db->domains, origin);
126762ac0c33Sjakob 	parser->prev_dname = parser->origin;
126862ac0c33Sjakob 	parser->error_occurred = 0;
126962ac0c33Sjakob 	parser->errors = 0;
127062ac0c33Sjakob 	parser->line = 1;
127162ac0c33Sjakob 	parser->filename = filename;
127262ac0c33Sjakob 	parser->current_rr.rdata_count = 0;
127362ac0c33Sjakob 	parser->current_rr.rdatas = parser->temporary_rdatas;
127462ac0c33Sjakob }
127562ac0c33Sjakob 
127662ac0c33Sjakob void
yyerror(const char * message)127762ac0c33Sjakob yyerror(const char *message)
127862ac0c33Sjakob {
127962ac0c33Sjakob 	zc_error("%s", message);
128062ac0c33Sjakob }
128162ac0c33Sjakob 
128262ac0c33Sjakob static void
error_va_list(unsigned line,const char * fmt,va_list args)128362ac0c33Sjakob error_va_list(unsigned line, const char *fmt, va_list args)
128462ac0c33Sjakob {
128562ac0c33Sjakob 	if (parser->filename) {
1286dd5b221eSsthen 		char message[MAXSYSLOGMSGLEN];
1287dd5b221eSsthen 		vsnprintf(message, sizeof(message), fmt, args);
1288dd5b221eSsthen 		log_msg(LOG_ERR, "%s:%u: %s", parser->filename, line, message);
128962ac0c33Sjakob 	}
1290dd5b221eSsthen 	else log_vmsg(LOG_ERR, fmt, args);
129162ac0c33Sjakob 
129262ac0c33Sjakob 	++parser->errors;
129362ac0c33Sjakob 	parser->error_occurred = 1;
129462ac0c33Sjakob }
129562ac0c33Sjakob 
129662ac0c33Sjakob /* the line counting sux, to say the least
129762ac0c33Sjakob  * with this grose hack we try do give sane
129862ac0c33Sjakob  * numbers back */
129962ac0c33Sjakob void
zc_error_prev_line(const char * fmt,...)130062ac0c33Sjakob zc_error_prev_line(const char *fmt, ...)
130162ac0c33Sjakob {
130262ac0c33Sjakob 	va_list args;
130362ac0c33Sjakob 	va_start(args, fmt);
130462ac0c33Sjakob 	error_va_list(parser->line - 1, fmt, args);
130562ac0c33Sjakob 	va_end(args);
130662ac0c33Sjakob }
130762ac0c33Sjakob 
130862ac0c33Sjakob void
zc_error(const char * fmt,...)130962ac0c33Sjakob zc_error(const char *fmt, ...)
131062ac0c33Sjakob {
131162ac0c33Sjakob 	/* send an error message to stderr */
131262ac0c33Sjakob 	va_list args;
131362ac0c33Sjakob 	va_start(args, fmt);
131462ac0c33Sjakob 	error_va_list(parser->line, fmt, args);
131562ac0c33Sjakob 	va_end(args);
131662ac0c33Sjakob }
131762ac0c33Sjakob 
131862ac0c33Sjakob static void
warning_va_list(unsigned line,const char * fmt,va_list args)131962ac0c33Sjakob warning_va_list(unsigned line, const char *fmt, va_list args)
132062ac0c33Sjakob {
132162ac0c33Sjakob 	if (parser->filename) {
1322dd5b221eSsthen 		char m[MAXSYSLOGMSGLEN];
1323dd5b221eSsthen 		vsnprintf(m, sizeof(m), fmt, args);
1324dd5b221eSsthen 		log_msg(LOG_WARNING, "%s:%u: %s", parser->filename, line, m);
132562ac0c33Sjakob 	}
1326dd5b221eSsthen 	else log_vmsg(LOG_WARNING, fmt, args);
132762ac0c33Sjakob }
132862ac0c33Sjakob 
132962ac0c33Sjakob void
zc_warning_prev_line(const char * fmt,...)133062ac0c33Sjakob zc_warning_prev_line(const char *fmt, ...)
133162ac0c33Sjakob {
133262ac0c33Sjakob 	va_list args;
133362ac0c33Sjakob 	va_start(args, fmt);
133462ac0c33Sjakob 	warning_va_list(parser->line - 1, fmt, args);
133562ac0c33Sjakob 	va_end(args);
133662ac0c33Sjakob }
133762ac0c33Sjakob 
133862ac0c33Sjakob void
zc_warning(const char * fmt,...)133962ac0c33Sjakob zc_warning(const char *fmt, ... )
134062ac0c33Sjakob {
134162ac0c33Sjakob 	va_list args;
134262ac0c33Sjakob 	va_start(args, fmt);
134362ac0c33Sjakob 	warning_va_list(parser->line, fmt, args);
134462ac0c33Sjakob 	va_end(args);
134562ac0c33Sjakob }
134662ac0c33Sjakob 
134762ac0c33Sjakob #ifdef NSEC3
134862ac0c33Sjakob static void
nsec3_add_params(const char * hashalgo_str,const char * flag_str,const char * iter_str,const char * salt_str,int salt_len)134962ac0c33Sjakob nsec3_add_params(const char* hashalgo_str, const char* flag_str,
135062ac0c33Sjakob 	const char* iter_str, const char* salt_str, int salt_len)
135162ac0c33Sjakob {
135262ac0c33Sjakob 	zadd_rdata_wireformat(zparser_conv_byte(parser->region, hashalgo_str));
135362ac0c33Sjakob 	zadd_rdata_wireformat(zparser_conv_byte(parser->region, flag_str));
135462ac0c33Sjakob 	zadd_rdata_wireformat(zparser_conv_short(parser->region, iter_str));
135562ac0c33Sjakob 
135662ac0c33Sjakob 	/* salt */
135762ac0c33Sjakob 	if(strcmp(salt_str, "-") != 0)
135862ac0c33Sjakob 		zadd_rdata_wireformat(zparser_conv_hex_length(parser->region,
135962ac0c33Sjakob 			salt_str, salt_len));
136062ac0c33Sjakob 	else
136162ac0c33Sjakob 		zadd_rdata_wireformat(alloc_rdata_init(parser->region, "", 1));
136262ac0c33Sjakob }
136362ac0c33Sjakob #endif /* NSEC3 */
1364