1package dns
2
3import (
4	"encoding/base64"
5	"net"
6	"strconv"
7	"strings"
8)
9
10type parserFunc struct {
11	// Func defines the function that parses the tokens and returns the RR
12	// or an error. The last string contains any comments in the line as
13	// they returned by the lexer as well.
14	Func func(h RR_Header, c chan lex, origin string, file string) (RR, *ParseError, string)
15	// Signals if the RR ending is of variable length, like TXT or records
16	// that have Hexadecimal or Base64 as their last element in the Rdata. Records
17	// that have a fixed ending or for instance A, AAAA, SOA and etc.
18	Variable bool
19}
20
21// Parse the rdata of each rrtype.
22// All data from the channel c is either zString or zBlank.
23// After the rdata there may come a zBlank and then a zNewline
24// or immediately a zNewline. If this is not the case we flag
25// an *ParseError: garbage after rdata.
26func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
27	parserfunc, ok := typeToparserFunc[h.Rrtype]
28	if ok {
29		r, e, cm := parserfunc.Func(h, c, o, f)
30		if parserfunc.Variable {
31			return r, e, cm
32		}
33		if e != nil {
34			return nil, e, ""
35		}
36		e, cm = slurpRemainder(c, f)
37		if e != nil {
38			return nil, e, ""
39		}
40		return r, nil, cm
41	}
42	// RFC3957 RR (Unknown RR handling)
43	return setRFC3597(h, c, o, f)
44}
45
46// A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
47// or an error
48func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) {
49	s := ""
50	l := <-c // zString
51	for l.value != zNewline && l.value != zEOF {
52		if l.err {
53			return s, &ParseError{f, errstr, l}, ""
54		}
55		switch l.value {
56		case zString:
57			s += l.token
58		case zBlank: // Ok
59		default:
60			return "", &ParseError{f, errstr, l}, ""
61		}
62		l = <-c
63	}
64	return s, nil, l.comment
65}
66
67// A remainder of the rdata with embedded spaces, split on unquoted whitespace
68// and return the parsed string slice or an error
69func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) {
70	// Get the remaining data until we see a zNewline
71	l := <-c
72	if l.err {
73		return nil, &ParseError{f, errstr, l}, ""
74	}
75
76	// Build the slice
77	s := make([]string, 0)
78	quote := false
79	empty := false
80	for l.value != zNewline && l.value != zEOF {
81		if l.err {
82			return nil, &ParseError{f, errstr, l}, ""
83		}
84		switch l.value {
85		case zString:
86			empty = false
87			if len(l.token) > 255 {
88				// split up tokens that are larger than 255 into 255-chunks
89				sx := []string{}
90				p, i := 0, 255
91				for {
92					if i <= len(l.token) {
93						sx = append(sx, l.token[p:i])
94					} else {
95						sx = append(sx, l.token[p:])
96						break
97
98					}
99					p, i = p+255, i+255
100				}
101				s = append(s, sx...)
102				break
103			}
104
105			s = append(s, l.token)
106		case zBlank:
107			if quote {
108				// zBlank can only be seen in between txt parts.
109				return nil, &ParseError{f, errstr, l}, ""
110			}
111		case zQuote:
112			if empty && quote {
113				s = append(s, "")
114			}
115			quote = !quote
116			empty = true
117		default:
118			return nil, &ParseError{f, errstr, l}, ""
119		}
120		l = <-c
121	}
122	if quote {
123		return nil, &ParseError{f, errstr, l}, ""
124	}
125	return s, nil, l.comment
126}
127
128func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
129	rr := new(A)
130	rr.Hdr = h
131
132	l := <-c
133	if l.length == 0 { // dynamic update rr.
134		return rr, nil, ""
135	}
136
137	rr.A = net.ParseIP(l.token)
138	if rr.A == nil || l.err {
139		return nil, &ParseError{f, "bad A A", l}, ""
140	}
141	return rr, nil, ""
142}
143
144func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
145	rr := new(AAAA)
146	rr.Hdr = h
147
148	l := <-c
149	if l.length == 0 { // dynamic update rr.
150		return rr, nil, ""
151	}
152
153	rr.AAAA = net.ParseIP(l.token)
154	if rr.AAAA == nil || l.err {
155		return nil, &ParseError{f, "bad AAAA AAAA", l}, ""
156	}
157	return rr, nil, ""
158}
159
160func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
161	rr := new(NS)
162	rr.Hdr = h
163
164	l := <-c
165	rr.Ns = l.token
166	if l.length == 0 { // dynamic update rr.
167		return rr, nil, ""
168	}
169
170	name, nameOk := toAbsoluteName(l.token, o)
171	if l.err || !nameOk {
172		return nil, &ParseError{f, "bad NS Ns", l}, ""
173	}
174	rr.Ns = name
175	return rr, nil, ""
176}
177
178func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
179	rr := new(PTR)
180	rr.Hdr = h
181
182	l := <-c
183	rr.Ptr = l.token
184	if l.length == 0 { // dynamic update rr.
185		return rr, nil, ""
186	}
187
188	name, nameOk := toAbsoluteName(l.token, o)
189	if l.err || !nameOk {
190		return nil, &ParseError{f, "bad PTR Ptr", l}, ""
191	}
192	rr.Ptr = name
193	return rr, nil, ""
194}
195
196func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
197	rr := new(NSAPPTR)
198	rr.Hdr = h
199
200	l := <-c
201	rr.Ptr = l.token
202	if l.length == 0 { // dynamic update rr.
203		return rr, nil, ""
204	}
205
206	name, nameOk := toAbsoluteName(l.token, o)
207	if l.err || !nameOk {
208		return nil, &ParseError{f, "bad NSAP-PTR Ptr", l}, ""
209	}
210	rr.Ptr = name
211	return rr, nil, ""
212}
213
214func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
215	rr := new(RP)
216	rr.Hdr = h
217
218	l := <-c
219	rr.Mbox = l.token
220	if l.length == 0 { // dynamic update rr.
221		return rr, nil, ""
222	}
223
224	mbox, mboxOk := toAbsoluteName(l.token, o)
225	if l.err || !mboxOk {
226		return nil, &ParseError{f, "bad RP Mbox", l}, ""
227	}
228	rr.Mbox = mbox
229
230	<-c // zBlank
231	l = <-c
232	rr.Txt = l.token
233
234	txt, txtOk := toAbsoluteName(l.token, o)
235	if l.err || !txtOk {
236		return nil, &ParseError{f, "bad RP Txt", l}, ""
237	}
238	rr.Txt = txt
239
240	return rr, nil, ""
241}
242
243func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
244	rr := new(MR)
245	rr.Hdr = h
246
247	l := <-c
248	rr.Mr = l.token
249	if l.length == 0 { // dynamic update rr.
250		return rr, nil, ""
251	}
252
253	name, nameOk := toAbsoluteName(l.token, o)
254	if l.err || !nameOk {
255		return nil, &ParseError{f, "bad MR Mr", l}, ""
256	}
257	rr.Mr = name
258	return rr, nil, ""
259}
260
261func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
262	rr := new(MB)
263	rr.Hdr = h
264
265	l := <-c
266	rr.Mb = l.token
267	if l.length == 0 { // dynamic update rr.
268		return rr, nil, ""
269	}
270
271	name, nameOk := toAbsoluteName(l.token, o)
272	if l.err || !nameOk {
273		return nil, &ParseError{f, "bad MB Mb", l}, ""
274	}
275	rr.Mb = name
276	return rr, nil, ""
277}
278
279func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
280	rr := new(MG)
281	rr.Hdr = h
282
283	l := <-c
284	rr.Mg = l.token
285	if l.length == 0 { // dynamic update rr.
286		return rr, nil, ""
287	}
288
289	name, nameOk := toAbsoluteName(l.token, o)
290	if l.err || !nameOk {
291		return nil, &ParseError{f, "bad MG Mg", l}, ""
292	}
293	rr.Mg = name
294	return rr, nil, ""
295}
296
297func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
298	rr := new(HINFO)
299	rr.Hdr = h
300
301	chunks, e, c1 := endingToTxtSlice(c, "bad HINFO Fields", f)
302	if e != nil {
303		return nil, e, c1
304	}
305
306	if ln := len(chunks); ln == 0 {
307		return rr, nil, ""
308	} else if ln == 1 {
309		// Can we split it?
310		if out := strings.Fields(chunks[0]); len(out) > 1 {
311			chunks = out
312		} else {
313			chunks = append(chunks, "")
314		}
315	}
316
317	rr.Cpu = chunks[0]
318	rr.Os = strings.Join(chunks[1:], " ")
319
320	return rr, nil, ""
321}
322
323func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
324	rr := new(MINFO)
325	rr.Hdr = h
326
327	l := <-c
328	rr.Rmail = l.token
329	if l.length == 0 { // dynamic update rr.
330		return rr, nil, ""
331	}
332
333	rmail, rmailOk := toAbsoluteName(l.token, o)
334	if l.err || !rmailOk {
335		return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
336	}
337	rr.Rmail = rmail
338
339	<-c // zBlank
340	l = <-c
341	rr.Email = l.token
342
343	email, emailOk := toAbsoluteName(l.token, o)
344	if l.err || !emailOk {
345		return nil, &ParseError{f, "bad MINFO Email", l}, ""
346	}
347	rr.Email = email
348
349	return rr, nil, ""
350}
351
352func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
353	rr := new(MF)
354	rr.Hdr = h
355
356	l := <-c
357	rr.Mf = l.token
358	if l.length == 0 { // dynamic update rr.
359		return rr, nil, ""
360	}
361
362	name, nameOk := toAbsoluteName(l.token, o)
363	if l.err || !nameOk {
364		return nil, &ParseError{f, "bad MF Mf", l}, ""
365	}
366	rr.Mf = name
367	return rr, nil, ""
368}
369
370func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
371	rr := new(MD)
372	rr.Hdr = h
373
374	l := <-c
375	rr.Md = l.token
376	if l.length == 0 { // dynamic update rr.
377		return rr, nil, ""
378	}
379
380	name, nameOk := toAbsoluteName(l.token, o)
381	if l.err || !nameOk {
382		return nil, &ParseError{f, "bad MD Md", l}, ""
383	}
384	rr.Md = name
385	return rr, nil, ""
386}
387
388func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
389	rr := new(MX)
390	rr.Hdr = h
391
392	l := <-c
393	if l.length == 0 { // dynamic update rr.
394		return rr, nil, ""
395	}
396
397	i, e := strconv.ParseUint(l.token, 10, 16)
398	if e != nil || l.err {
399		return nil, &ParseError{f, "bad MX Pref", l}, ""
400	}
401	rr.Preference = uint16(i)
402
403	<-c     // zBlank
404	l = <-c // zString
405	rr.Mx = l.token
406
407	name, nameOk := toAbsoluteName(l.token, o)
408	if l.err || !nameOk {
409		return nil, &ParseError{f, "bad MX Mx", l}, ""
410	}
411	rr.Mx = name
412
413	return rr, nil, ""
414}
415
416func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
417	rr := new(RT)
418	rr.Hdr = h
419
420	l := <-c
421	if l.length == 0 { // dynamic update rr.
422		return rr, nil, ""
423	}
424
425	i, e := strconv.ParseUint(l.token, 10, 16)
426	if e != nil {
427		return nil, &ParseError{f, "bad RT Preference", l}, ""
428	}
429	rr.Preference = uint16(i)
430
431	<-c     // zBlank
432	l = <-c // zString
433	rr.Host = l.token
434
435	name, nameOk := toAbsoluteName(l.token, o)
436	if l.err || !nameOk {
437		return nil, &ParseError{f, "bad RT Host", l}, ""
438	}
439	rr.Host = name
440
441	return rr, nil, ""
442}
443
444func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
445	rr := new(AFSDB)
446	rr.Hdr = h
447
448	l := <-c
449	if l.length == 0 { // dynamic update rr.
450		return rr, nil, ""
451	}
452
453	i, e := strconv.ParseUint(l.token, 10, 16)
454	if e != nil || l.err {
455		return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
456	}
457	rr.Subtype = uint16(i)
458
459	<-c     // zBlank
460	l = <-c // zString
461	rr.Hostname = l.token
462
463	name, nameOk := toAbsoluteName(l.token, o)
464	if l.err || !nameOk {
465		return nil, &ParseError{f, "bad AFSDB Hostname", l}, ""
466	}
467	rr.Hostname = name
468	return rr, nil, ""
469}
470
471func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
472	rr := new(X25)
473	rr.Hdr = h
474
475	l := <-c
476	if l.length == 0 { // dynamic update rr.
477		return rr, nil, ""
478	}
479
480	if l.err {
481		return nil, &ParseError{f, "bad X25 PSDNAddress", l}, ""
482	}
483	rr.PSDNAddress = l.token
484	return rr, nil, ""
485}
486
487func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
488	rr := new(KX)
489	rr.Hdr = h
490
491	l := <-c
492	if l.length == 0 { // dynamic update rr.
493		return rr, nil, ""
494	}
495
496	i, e := strconv.ParseUint(l.token, 10, 16)
497	if e != nil || l.err {
498		return nil, &ParseError{f, "bad KX Pref", l}, ""
499	}
500	rr.Preference = uint16(i)
501
502	<-c     // zBlank
503	l = <-c // zString
504	rr.Exchanger = l.token
505
506	name, nameOk := toAbsoluteName(l.token, o)
507	if l.err || !nameOk {
508		return nil, &ParseError{f, "bad KX Exchanger", l}, ""
509	}
510	rr.Exchanger = name
511	return rr, nil, ""
512}
513
514func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
515	rr := new(CNAME)
516	rr.Hdr = h
517
518	l := <-c
519	rr.Target = l.token
520	if l.length == 0 { // dynamic update rr.
521		return rr, nil, ""
522	}
523
524	name, nameOk := toAbsoluteName(l.token, o)
525	if l.err || !nameOk {
526		return nil, &ParseError{f, "bad CNAME Target", l}, ""
527	}
528	rr.Target = name
529	return rr, nil, ""
530}
531
532func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
533	rr := new(DNAME)
534	rr.Hdr = h
535
536	l := <-c
537	rr.Target = l.token
538	if l.length == 0 { // dynamic update rr.
539		return rr, nil, ""
540	}
541
542	name, nameOk := toAbsoluteName(l.token, o)
543	if l.err || !nameOk {
544		return nil, &ParseError{f, "bad DNAME Target", l}, ""
545	}
546	rr.Target = name
547	return rr, nil, ""
548}
549
550func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
551	rr := new(SOA)
552	rr.Hdr = h
553
554	l := <-c
555	rr.Ns = l.token
556	if l.length == 0 { // dynamic update rr.
557		return rr, nil, ""
558	}
559
560	ns, nsOk := toAbsoluteName(l.token, o)
561	if l.err || !nsOk {
562		return nil, &ParseError{f, "bad SOA Ns", l}, ""
563	}
564	rr.Ns = ns
565
566	<-c // zBlank
567	l = <-c
568	rr.Mbox = l.token
569
570	mbox, mboxOk := toAbsoluteName(l.token, o)
571	if l.err || !mboxOk {
572		return nil, &ParseError{f, "bad SOA Mbox", l}, ""
573	}
574	rr.Mbox = mbox
575
576	<-c // zBlank
577
578	var (
579		v  uint32
580		ok bool
581	)
582	for i := 0; i < 5; i++ {
583		l = <-c
584		if l.err {
585			return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
586		}
587		if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
588			if i == 0 {
589				// Serial must be a number
590				return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
591			}
592			// We allow other fields to be unitful duration strings
593			if v, ok = stringToTTL(l.token); !ok {
594				return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
595
596			}
597		} else {
598			v = uint32(j)
599		}
600		switch i {
601		case 0:
602			rr.Serial = v
603			<-c // zBlank
604		case 1:
605			rr.Refresh = v
606			<-c // zBlank
607		case 2:
608			rr.Retry = v
609			<-c // zBlank
610		case 3:
611			rr.Expire = v
612			<-c // zBlank
613		case 4:
614			rr.Minttl = v
615		}
616	}
617	return rr, nil, ""
618}
619
620func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
621	rr := new(SRV)
622	rr.Hdr = h
623
624	l := <-c
625	if l.length == 0 { // dynamic update rr.
626		return rr, nil, ""
627	}
628
629	i, e := strconv.ParseUint(l.token, 10, 16)
630	if e != nil || l.err {
631		return nil, &ParseError{f, "bad SRV Priority", l}, ""
632	}
633	rr.Priority = uint16(i)
634
635	<-c     // zBlank
636	l = <-c // zString
637	i, e = strconv.ParseUint(l.token, 10, 16)
638	if e != nil || l.err {
639		return nil, &ParseError{f, "bad SRV Weight", l}, ""
640	}
641	rr.Weight = uint16(i)
642
643	<-c     // zBlank
644	l = <-c // zString
645	i, e = strconv.ParseUint(l.token, 10, 16)
646	if e != nil || l.err {
647		return nil, &ParseError{f, "bad SRV Port", l}, ""
648	}
649	rr.Port = uint16(i)
650
651	<-c     // zBlank
652	l = <-c // zString
653	rr.Target = l.token
654
655	name, nameOk := toAbsoluteName(l.token, o)
656	if l.err || !nameOk {
657		return nil, &ParseError{f, "bad SRV Target", l}, ""
658	}
659	rr.Target = name
660	return rr, nil, ""
661}
662
663func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
664	rr := new(NAPTR)
665	rr.Hdr = h
666
667	l := <-c
668	if l.length == 0 { // dynamic update rr.
669		return rr, nil, ""
670	}
671
672	i, e := strconv.ParseUint(l.token, 10, 16)
673	if e != nil || l.err {
674		return nil, &ParseError{f, "bad NAPTR Order", l}, ""
675	}
676	rr.Order = uint16(i)
677
678	<-c     // zBlank
679	l = <-c // zString
680	i, e = strconv.ParseUint(l.token, 10, 16)
681	if e != nil || l.err {
682		return nil, &ParseError{f, "bad NAPTR Preference", l}, ""
683	}
684	rr.Preference = uint16(i)
685
686	// Flags
687	<-c     // zBlank
688	l = <-c // _QUOTE
689	if l.value != zQuote {
690		return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
691	}
692	l = <-c // Either String or Quote
693	if l.value == zString {
694		rr.Flags = l.token
695		l = <-c // _QUOTE
696		if l.value != zQuote {
697			return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
698		}
699	} else if l.value == zQuote {
700		rr.Flags = ""
701	} else {
702		return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
703	}
704
705	// Service
706	<-c     // zBlank
707	l = <-c // _QUOTE
708	if l.value != zQuote {
709		return nil, &ParseError{f, "bad NAPTR Service", l}, ""
710	}
711	l = <-c // Either String or Quote
712	if l.value == zString {
713		rr.Service = l.token
714		l = <-c // _QUOTE
715		if l.value != zQuote {
716			return nil, &ParseError{f, "bad NAPTR Service", l}, ""
717		}
718	} else if l.value == zQuote {
719		rr.Service = ""
720	} else {
721		return nil, &ParseError{f, "bad NAPTR Service", l}, ""
722	}
723
724	// Regexp
725	<-c     // zBlank
726	l = <-c // _QUOTE
727	if l.value != zQuote {
728		return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
729	}
730	l = <-c // Either String or Quote
731	if l.value == zString {
732		rr.Regexp = l.token
733		l = <-c // _QUOTE
734		if l.value != zQuote {
735			return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
736		}
737	} else if l.value == zQuote {
738		rr.Regexp = ""
739	} else {
740		return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
741	}
742
743	// After quote no space??
744	<-c     // zBlank
745	l = <-c // zString
746	rr.Replacement = l.token
747
748	name, nameOk := toAbsoluteName(l.token, o)
749	if l.err || !nameOk {
750		return nil, &ParseError{f, "bad NAPTR Replacement", l}, ""
751	}
752	rr.Replacement = name
753	return rr, nil, ""
754}
755
756func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
757	rr := new(TALINK)
758	rr.Hdr = h
759
760	l := <-c
761	rr.PreviousName = l.token
762	if l.length == 0 { // dynamic update rr.
763		return rr, nil, ""
764	}
765
766	previousName, previousNameOk := toAbsoluteName(l.token, o)
767	if l.err || !previousNameOk {
768		return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
769	}
770	rr.PreviousName = previousName
771
772	<-c // zBlank
773	l = <-c
774	rr.NextName = l.token
775
776	nextName, nextNameOk := toAbsoluteName(l.token, o)
777	if l.err || !nextNameOk {
778		return nil, &ParseError{f, "bad TALINK NextName", l}, ""
779	}
780	rr.NextName = nextName
781
782	return rr, nil, ""
783}
784
785func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
786	rr := new(LOC)
787	rr.Hdr = h
788	// Non zero defaults for LOC record, see RFC 1876, Section 3.
789	rr.HorizPre = 165 // 10000
790	rr.VertPre = 162  // 10
791	rr.Size = 18      // 1
792	ok := false
793
794	// North
795	l := <-c
796	if l.length == 0 { // dynamic update rr.
797		return rr, nil, ""
798	}
799	i, e := strconv.ParseUint(l.token, 10, 32)
800	if e != nil || l.err {
801		return nil, &ParseError{f, "bad LOC Latitude", l}, ""
802	}
803	rr.Latitude = 1000 * 60 * 60 * uint32(i)
804
805	<-c // zBlank
806	// Either number, 'N' or 'S'
807	l = <-c
808	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
809		goto East
810	}
811	i, e = strconv.ParseUint(l.token, 10, 32)
812	if e != nil || l.err {
813		return nil, &ParseError{f, "bad LOC Latitude minutes", l}, ""
814	}
815	rr.Latitude += 1000 * 60 * uint32(i)
816
817	<-c // zBlank
818	l = <-c
819	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
820		return nil, &ParseError{f, "bad LOC Latitude seconds", l}, ""
821	} else {
822		rr.Latitude += uint32(1000 * i)
823	}
824	<-c // zBlank
825	// Either number, 'N' or 'S'
826	l = <-c
827	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
828		goto East
829	}
830	// If still alive, flag an error
831	return nil, &ParseError{f, "bad LOC Latitude North/South", l}, ""
832
833East:
834	// East
835	<-c // zBlank
836	l = <-c
837	if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
838		return nil, &ParseError{f, "bad LOC Longitude", l}, ""
839	} else {
840		rr.Longitude = 1000 * 60 * 60 * uint32(i)
841	}
842	<-c // zBlank
843	// Either number, 'E' or 'W'
844	l = <-c
845	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
846		goto Altitude
847	}
848	if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
849		return nil, &ParseError{f, "bad LOC Longitude minutes", l}, ""
850	} else {
851		rr.Longitude += 1000 * 60 * uint32(i)
852	}
853	<-c // zBlank
854	l = <-c
855	if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
856		return nil, &ParseError{f, "bad LOC Longitude seconds", l}, ""
857	} else {
858		rr.Longitude += uint32(1000 * i)
859	}
860	<-c // zBlank
861	// Either number, 'E' or 'W'
862	l = <-c
863	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
864		goto Altitude
865	}
866	// If still alive, flag an error
867	return nil, &ParseError{f, "bad LOC Longitude East/West", l}, ""
868
869Altitude:
870	<-c // zBlank
871	l = <-c
872	if l.length == 0 || l.err {
873		return nil, &ParseError{f, "bad LOC Altitude", l}, ""
874	}
875	if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
876		l.token = l.token[0 : len(l.token)-1]
877	}
878	if i, e := strconv.ParseFloat(l.token, 32); e != nil {
879		return nil, &ParseError{f, "bad LOC Altitude", l}, ""
880	} else {
881		rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
882	}
883
884	// And now optionally the other values
885	l = <-c
886	count := 0
887	for l.value != zNewline && l.value != zEOF {
888		switch l.value {
889		case zString:
890			switch count {
891			case 0: // Size
892				e, m, ok := stringToCm(l.token)
893				if !ok {
894					return nil, &ParseError{f, "bad LOC Size", l}, ""
895				}
896				rr.Size = (e & 0x0f) | (m << 4 & 0xf0)
897			case 1: // HorizPre
898				e, m, ok := stringToCm(l.token)
899				if !ok {
900					return nil, &ParseError{f, "bad LOC HorizPre", l}, ""
901				}
902				rr.HorizPre = (e & 0x0f) | (m << 4 & 0xf0)
903			case 2: // VertPre
904				e, m, ok := stringToCm(l.token)
905				if !ok {
906					return nil, &ParseError{f, "bad LOC VertPre", l}, ""
907				}
908				rr.VertPre = (e & 0x0f) | (m << 4 & 0xf0)
909			}
910			count++
911		case zBlank:
912			// Ok
913		default:
914			return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, ""
915		}
916		l = <-c
917	}
918	return rr, nil, ""
919}
920
921func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
922	rr := new(HIP)
923	rr.Hdr = h
924
925	// HitLength is not represented
926	l := <-c
927	if l.length == 0 { // dynamic update rr.
928		return rr, nil, l.comment
929	}
930
931	i, e := strconv.ParseUint(l.token, 10, 8)
932	if e != nil || l.err {
933		return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l}, ""
934	}
935	rr.PublicKeyAlgorithm = uint8(i)
936
937	<-c     // zBlank
938	l = <-c // zString
939	if l.length == 0 || l.err {
940		return nil, &ParseError{f, "bad HIP Hit", l}, ""
941	}
942	rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
943	rr.HitLength = uint8(len(rr.Hit)) / 2
944
945	<-c     // zBlank
946	l = <-c // zString
947	if l.length == 0 || l.err {
948		return nil, &ParseError{f, "bad HIP PublicKey", l}, ""
949	}
950	rr.PublicKey = l.token // This cannot contain spaces
951	rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey)))
952
953	// RendezvousServers (if any)
954	l = <-c
955	var xs []string
956	for l.value != zNewline && l.value != zEOF {
957		switch l.value {
958		case zString:
959			name, nameOk := toAbsoluteName(l.token, o)
960			if l.err || !nameOk {
961				return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
962			}
963			xs = append(xs, name)
964		case zBlank:
965			// Ok
966		default:
967			return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
968		}
969		l = <-c
970	}
971	rr.RendezvousServers = xs
972	return rr, nil, l.comment
973}
974
975func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
976	rr := new(CERT)
977	rr.Hdr = h
978
979	l := <-c
980	if l.length == 0 { // dynamic update rr.
981		return rr, nil, l.comment
982	}
983
984	if v, ok := StringToCertType[l.token]; ok {
985		rr.Type = v
986	} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
987		return nil, &ParseError{f, "bad CERT Type", l}, ""
988	} else {
989		rr.Type = uint16(i)
990	}
991	<-c     // zBlank
992	l = <-c // zString
993	i, e := strconv.ParseUint(l.token, 10, 16)
994	if e != nil || l.err {
995		return nil, &ParseError{f, "bad CERT KeyTag", l}, ""
996	}
997	rr.KeyTag = uint16(i)
998	<-c     // zBlank
999	l = <-c // zString
1000	if v, ok := StringToAlgorithm[l.token]; ok {
1001		rr.Algorithm = v
1002	} else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
1003		return nil, &ParseError{f, "bad CERT Algorithm", l}, ""
1004	} else {
1005		rr.Algorithm = uint8(i)
1006	}
1007	s, e1, c1 := endingToString(c, "bad CERT Certificate", f)
1008	if e1 != nil {
1009		return nil, e1, c1
1010	}
1011	rr.Certificate = s
1012	return rr, nil, c1
1013}
1014
1015func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1016	rr := new(OPENPGPKEY)
1017	rr.Hdr = h
1018
1019	s, e, c1 := endingToString(c, "bad OPENPGPKEY PublicKey", f)
1020	if e != nil {
1021		return nil, e, c1
1022	}
1023	rr.PublicKey = s
1024	return rr, nil, c1
1025}
1026
1027func setCSYNC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1028	rr := new(CSYNC)
1029	rr.Hdr = h
1030
1031	l := <-c
1032	if l.length == 0 { // dynamic update rr.
1033		return rr, nil, l.comment
1034	}
1035	j, e := strconv.ParseUint(l.token, 10, 32)
1036	if e != nil {
1037		// Serial must be a number
1038		return nil, &ParseError{f, "bad CSYNC serial", l}, ""
1039	}
1040	rr.Serial = uint32(j)
1041
1042	<-c // zBlank
1043
1044	l = <-c
1045	j, e = strconv.ParseUint(l.token, 10, 16)
1046	if e != nil {
1047		// Serial must be a number
1048		return nil, &ParseError{f, "bad CSYNC flags", l}, ""
1049	}
1050	rr.Flags = uint16(j)
1051
1052	rr.TypeBitMap = make([]uint16, 0)
1053	var (
1054		k  uint16
1055		ok bool
1056	)
1057	l = <-c
1058	for l.value != zNewline && l.value != zEOF {
1059		switch l.value {
1060		case zBlank:
1061			// Ok
1062		case zString:
1063			if k, ok = StringToType[l.tokenUpper]; !ok {
1064				if k, ok = typeToInt(l.tokenUpper); !ok {
1065					return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
1066				}
1067			}
1068			rr.TypeBitMap = append(rr.TypeBitMap, k)
1069		default:
1070			return nil, &ParseError{f, "bad CSYNC TypeBitMap", l}, ""
1071		}
1072		l = <-c
1073	}
1074	return rr, nil, l.comment
1075}
1076
1077func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1078	r, e, s := setRRSIG(h, c, o, f)
1079	if r != nil {
1080		return &SIG{*r.(*RRSIG)}, e, s
1081	}
1082	return nil, e, s
1083}
1084
1085func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1086	rr := new(RRSIG)
1087	rr.Hdr = h
1088
1089	l := <-c
1090	if l.length == 0 { // dynamic update rr.
1091		return rr, nil, l.comment
1092	}
1093
1094	if t, ok := StringToType[l.tokenUpper]; !ok {
1095		if strings.HasPrefix(l.tokenUpper, "TYPE") {
1096			t, ok = typeToInt(l.tokenUpper)
1097			if !ok {
1098				return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
1099			}
1100			rr.TypeCovered = t
1101		} else {
1102			return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
1103		}
1104	} else {
1105		rr.TypeCovered = t
1106	}
1107
1108	<-c // zBlank
1109	l = <-c
1110	i, err := strconv.ParseUint(l.token, 10, 8)
1111	if err != nil || l.err {
1112		return nil, &ParseError{f, "bad RRSIG Algorithm", l}, ""
1113	}
1114	rr.Algorithm = uint8(i)
1115
1116	<-c // zBlank
1117	l = <-c
1118	i, err = strconv.ParseUint(l.token, 10, 8)
1119	if err != nil || l.err {
1120		return nil, &ParseError{f, "bad RRSIG Labels", l}, ""
1121	}
1122	rr.Labels = uint8(i)
1123
1124	<-c // zBlank
1125	l = <-c
1126	i, err = strconv.ParseUint(l.token, 10, 32)
1127	if err != nil || l.err {
1128		return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, ""
1129	}
1130	rr.OrigTtl = uint32(i)
1131
1132	<-c // zBlank
1133	l = <-c
1134	if i, err := StringToTime(l.token); err != nil {
1135		// Try to see if all numeric and use it as epoch
1136		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
1137			// TODO(miek): error out on > MAX_UINT32, same below
1138			rr.Expiration = uint32(i)
1139		} else {
1140			return nil, &ParseError{f, "bad RRSIG Expiration", l}, ""
1141		}
1142	} else {
1143		rr.Expiration = i
1144	}
1145
1146	<-c // zBlank
1147	l = <-c
1148	if i, err := StringToTime(l.token); err != nil {
1149		if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
1150			rr.Inception = uint32(i)
1151		} else {
1152			return nil, &ParseError{f, "bad RRSIG Inception", l}, ""
1153		}
1154	} else {
1155		rr.Inception = i
1156	}
1157
1158	<-c // zBlank
1159	l = <-c
1160	i, err = strconv.ParseUint(l.token, 10, 16)
1161	if err != nil || l.err {
1162		return nil, &ParseError{f, "bad RRSIG KeyTag", l}, ""
1163	}
1164	rr.KeyTag = uint16(i)
1165
1166	<-c // zBlank
1167	l = <-c
1168	rr.SignerName = l.token
1169	name, nameOk := toAbsoluteName(l.token, o)
1170	if l.err || !nameOk {
1171		return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
1172	}
1173	rr.SignerName = name
1174
1175	s, e, c1 := endingToString(c, "bad RRSIG Signature", f)
1176	if e != nil {
1177		return nil, e, c1
1178	}
1179	rr.Signature = s
1180
1181	return rr, nil, c1
1182}
1183
1184func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1185	rr := new(NSEC)
1186	rr.Hdr = h
1187
1188	l := <-c
1189	rr.NextDomain = l.token
1190	if l.length == 0 { // dynamic update rr.
1191		return rr, nil, l.comment
1192	}
1193
1194	name, nameOk := toAbsoluteName(l.token, o)
1195	if l.err || !nameOk {
1196		return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
1197	}
1198	rr.NextDomain = name
1199
1200	rr.TypeBitMap = make([]uint16, 0)
1201	var (
1202		k  uint16
1203		ok bool
1204	)
1205	l = <-c
1206	for l.value != zNewline && l.value != zEOF {
1207		switch l.value {
1208		case zBlank:
1209			// Ok
1210		case zString:
1211			if k, ok = StringToType[l.tokenUpper]; !ok {
1212				if k, ok = typeToInt(l.tokenUpper); !ok {
1213					return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
1214				}
1215			}
1216			rr.TypeBitMap = append(rr.TypeBitMap, k)
1217		default:
1218			return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
1219		}
1220		l = <-c
1221	}
1222	return rr, nil, l.comment
1223}
1224
1225func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1226	rr := new(NSEC3)
1227	rr.Hdr = h
1228
1229	l := <-c
1230	if l.length == 0 { // dynamic update rr.
1231		return rr, nil, l.comment
1232	}
1233
1234	i, e := strconv.ParseUint(l.token, 10, 8)
1235	if e != nil || l.err {
1236		return nil, &ParseError{f, "bad NSEC3 Hash", l}, ""
1237	}
1238	rr.Hash = uint8(i)
1239	<-c // zBlank
1240	l = <-c
1241	i, e = strconv.ParseUint(l.token, 10, 8)
1242	if e != nil || l.err {
1243		return nil, &ParseError{f, "bad NSEC3 Flags", l}, ""
1244	}
1245	rr.Flags = uint8(i)
1246	<-c // zBlank
1247	l = <-c
1248	i, e = strconv.ParseUint(l.token, 10, 16)
1249	if e != nil || l.err {
1250		return nil, &ParseError{f, "bad NSEC3 Iterations", l}, ""
1251	}
1252	rr.Iterations = uint16(i)
1253	<-c
1254	l = <-c
1255	if len(l.token) == 0 || l.err {
1256		return nil, &ParseError{f, "bad NSEC3 Salt", l}, ""
1257	}
1258	rr.SaltLength = uint8(len(l.token)) / 2
1259	rr.Salt = l.token
1260
1261	<-c
1262	l = <-c
1263	if len(l.token) == 0 || l.err {
1264		return nil, &ParseError{f, "bad NSEC3 NextDomain", l}, ""
1265	}
1266	rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
1267	rr.NextDomain = l.token
1268
1269	rr.TypeBitMap = make([]uint16, 0)
1270	var (
1271		k  uint16
1272		ok bool
1273	)
1274	l = <-c
1275	for l.value != zNewline && l.value != zEOF {
1276		switch l.value {
1277		case zBlank:
1278			// Ok
1279		case zString:
1280			if k, ok = StringToType[l.tokenUpper]; !ok {
1281				if k, ok = typeToInt(l.tokenUpper); !ok {
1282					return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
1283				}
1284			}
1285			rr.TypeBitMap = append(rr.TypeBitMap, k)
1286		default:
1287			return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
1288		}
1289		l = <-c
1290	}
1291	return rr, nil, l.comment
1292}
1293
1294func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1295	rr := new(NSEC3PARAM)
1296	rr.Hdr = h
1297
1298	l := <-c
1299	if l.length == 0 { // dynamic update rr.
1300		return rr, nil, ""
1301	}
1302
1303	i, e := strconv.ParseUint(l.token, 10, 8)
1304	if e != nil || l.err {
1305		return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, ""
1306	}
1307	rr.Hash = uint8(i)
1308	<-c // zBlank
1309	l = <-c
1310	i, e = strconv.ParseUint(l.token, 10, 8)
1311	if e != nil || l.err {
1312		return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, ""
1313	}
1314	rr.Flags = uint8(i)
1315	<-c // zBlank
1316	l = <-c
1317	i, e = strconv.ParseUint(l.token, 10, 16)
1318	if e != nil || l.err {
1319		return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, ""
1320	}
1321	rr.Iterations = uint16(i)
1322	<-c
1323	l = <-c
1324	rr.SaltLength = uint8(len(l.token))
1325	rr.Salt = l.token
1326	return rr, nil, ""
1327}
1328
1329func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1330	rr := new(EUI48)
1331	rr.Hdr = h
1332
1333	l := <-c
1334	if l.length == 0 { // dynamic update rr.
1335		return rr, nil, ""
1336	}
1337
1338	if l.length != 17 || l.err {
1339		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
1340	}
1341	addr := make([]byte, 12)
1342	dash := 0
1343	for i := 0; i < 10; i += 2 {
1344		addr[i] = l.token[i+dash]
1345		addr[i+1] = l.token[i+1+dash]
1346		dash++
1347		if l.token[i+1+dash] != '-' {
1348			return nil, &ParseError{f, "bad EUI48 Address", l}, ""
1349		}
1350	}
1351	addr[10] = l.token[15]
1352	addr[11] = l.token[16]
1353
1354	i, e := strconv.ParseUint(string(addr), 16, 48)
1355	if e != nil {
1356		return nil, &ParseError{f, "bad EUI48 Address", l}, ""
1357	}
1358	rr.Address = i
1359	return rr, nil, ""
1360}
1361
1362func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1363	rr := new(EUI64)
1364	rr.Hdr = h
1365
1366	l := <-c
1367	if l.length == 0 { // dynamic update rr.
1368		return rr, nil, ""
1369	}
1370
1371	if l.length != 23 || l.err {
1372		return nil, &ParseError{f, "bad EUI64 Address", l}, ""
1373	}
1374	addr := make([]byte, 16)
1375	dash := 0
1376	for i := 0; i < 14; i += 2 {
1377		addr[i] = l.token[i+dash]
1378		addr[i+1] = l.token[i+1+dash]
1379		dash++
1380		if l.token[i+1+dash] != '-' {
1381			return nil, &ParseError{f, "bad EUI64 Address", l}, ""
1382		}
1383	}
1384	addr[14] = l.token[21]
1385	addr[15] = l.token[22]
1386
1387	i, e := strconv.ParseUint(string(addr), 16, 64)
1388	if e != nil {
1389		return nil, &ParseError{f, "bad EUI68 Address", l}, ""
1390	}
1391	rr.Address = uint64(i)
1392	return rr, nil, ""
1393}
1394
1395func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1396	rr := new(SSHFP)
1397	rr.Hdr = h
1398
1399	l := <-c
1400	if l.length == 0 { // dynamic update rr.
1401		return rr, nil, ""
1402	}
1403
1404	i, e := strconv.ParseUint(l.token, 10, 8)
1405	if e != nil || l.err {
1406		return nil, &ParseError{f, "bad SSHFP Algorithm", l}, ""
1407	}
1408	rr.Algorithm = uint8(i)
1409	<-c // zBlank
1410	l = <-c
1411	i, e = strconv.ParseUint(l.token, 10, 8)
1412	if e != nil || l.err {
1413		return nil, &ParseError{f, "bad SSHFP Type", l}, ""
1414	}
1415	rr.Type = uint8(i)
1416	<-c // zBlank
1417	s, e1, c1 := endingToString(c, "bad SSHFP Fingerprint", f)
1418	if e1 != nil {
1419		return nil, e1, c1
1420	}
1421	rr.FingerPrint = s
1422	return rr, nil, ""
1423}
1424
1425func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
1426	rr := new(DNSKEY)
1427	rr.Hdr = h
1428
1429	l := <-c
1430	if l.length == 0 { // dynamic update rr.
1431		return rr, nil, l.comment
1432	}
1433
1434	i, e := strconv.ParseUint(l.token, 10, 16)
1435	if e != nil || l.err {
1436		return nil, &ParseError{f, "bad " + typ + " Flags", l}, ""
1437	}
1438	rr.Flags = uint16(i)
1439	<-c     // zBlank
1440	l = <-c // zString
1441	i, e = strconv.ParseUint(l.token, 10, 8)
1442	if e != nil || l.err {
1443		return nil, &ParseError{f, "bad " + typ + " Protocol", l}, ""
1444	}
1445	rr.Protocol = uint8(i)
1446	<-c     // zBlank
1447	l = <-c // zString
1448	i, e = strconv.ParseUint(l.token, 10, 8)
1449	if e != nil || l.err {
1450		return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
1451	}
1452	rr.Algorithm = uint8(i)
1453	s, e1, c1 := endingToString(c, "bad "+typ+" PublicKey", f)
1454	if e1 != nil {
1455		return nil, e1, c1
1456	}
1457	rr.PublicKey = s
1458	return rr, nil, c1
1459}
1460
1461func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1462	r, e, s := setDNSKEYs(h, c, o, f, "KEY")
1463	if r != nil {
1464		return &KEY{*r.(*DNSKEY)}, e, s
1465	}
1466	return nil, e, s
1467}
1468
1469func setDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1470	r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY")
1471	return r, e, s
1472}
1473
1474func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1475	r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY")
1476	if r != nil {
1477		return &CDNSKEY{*r.(*DNSKEY)}, e, s
1478	}
1479	return nil, e, s
1480}
1481
1482func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1483	rr := new(RKEY)
1484	rr.Hdr = h
1485
1486	l := <-c
1487	if l.length == 0 { // dynamic update rr.
1488		return rr, nil, l.comment
1489	}
1490
1491	i, e := strconv.ParseUint(l.token, 10, 16)
1492	if e != nil || l.err {
1493		return nil, &ParseError{f, "bad RKEY Flags", l}, ""
1494	}
1495	rr.Flags = uint16(i)
1496	<-c     // zBlank
1497	l = <-c // zString
1498	i, e = strconv.ParseUint(l.token, 10, 8)
1499	if e != nil || l.err {
1500		return nil, &ParseError{f, "bad RKEY Protocol", l}, ""
1501	}
1502	rr.Protocol = uint8(i)
1503	<-c     // zBlank
1504	l = <-c // zString
1505	i, e = strconv.ParseUint(l.token, 10, 8)
1506	if e != nil || l.err {
1507		return nil, &ParseError{f, "bad RKEY Algorithm", l}, ""
1508	}
1509	rr.Algorithm = uint8(i)
1510	s, e1, c1 := endingToString(c, "bad RKEY PublicKey", f)
1511	if e1 != nil {
1512		return nil, e1, c1
1513	}
1514	rr.PublicKey = s
1515	return rr, nil, c1
1516}
1517
1518func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1519	rr := new(EID)
1520	rr.Hdr = h
1521	s, e, c1 := endingToString(c, "bad EID Endpoint", f)
1522	if e != nil {
1523		return nil, e, c1
1524	}
1525	rr.Endpoint = s
1526	return rr, nil, c1
1527}
1528
1529func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1530	rr := new(NIMLOC)
1531	rr.Hdr = h
1532	s, e, c1 := endingToString(c, "bad NIMLOC Locator", f)
1533	if e != nil {
1534		return nil, e, c1
1535	}
1536	rr.Locator = s
1537	return rr, nil, c1
1538}
1539
1540func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1541	rr := new(GPOS)
1542	rr.Hdr = h
1543
1544	l := <-c
1545	if l.length == 0 { // dynamic update rr.
1546		return rr, nil, ""
1547	}
1548
1549	_, e := strconv.ParseFloat(l.token, 64)
1550	if e != nil || l.err {
1551		return nil, &ParseError{f, "bad GPOS Longitude", l}, ""
1552	}
1553	rr.Longitude = l.token
1554	<-c // zBlank
1555	l = <-c
1556	_, e = strconv.ParseFloat(l.token, 64)
1557	if e != nil || l.err {
1558		return nil, &ParseError{f, "bad GPOS Latitude", l}, ""
1559	}
1560	rr.Latitude = l.token
1561	<-c // zBlank
1562	l = <-c
1563	_, e = strconv.ParseFloat(l.token, 64)
1564	if e != nil || l.err {
1565		return nil, &ParseError{f, "bad GPOS Altitude", l}, ""
1566	}
1567	rr.Altitude = l.token
1568	return rr, nil, ""
1569}
1570
1571func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
1572	rr := new(DS)
1573	rr.Hdr = h
1574
1575	l := <-c
1576	if l.length == 0 { // dynamic update rr.
1577		return rr, nil, l.comment
1578	}
1579
1580	i, e := strconv.ParseUint(l.token, 10, 16)
1581	if e != nil || l.err {
1582		return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, ""
1583	}
1584	rr.KeyTag = uint16(i)
1585	<-c // zBlank
1586	l = <-c
1587	if i, e = strconv.ParseUint(l.token, 10, 8); e != nil {
1588		i, ok := StringToAlgorithm[l.tokenUpper]
1589		if !ok || l.err {
1590			return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
1591		}
1592		rr.Algorithm = i
1593	} else {
1594		rr.Algorithm = uint8(i)
1595	}
1596	<-c // zBlank
1597	l = <-c
1598	i, e = strconv.ParseUint(l.token, 10, 8)
1599	if e != nil || l.err {
1600		return nil, &ParseError{f, "bad " + typ + " DigestType", l}, ""
1601	}
1602	rr.DigestType = uint8(i)
1603	s, e1, c1 := endingToString(c, "bad "+typ+" Digest", f)
1604	if e1 != nil {
1605		return nil, e1, c1
1606	}
1607	rr.Digest = s
1608	return rr, nil, c1
1609}
1610
1611func setDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1612	r, e, s := setDSs(h, c, o, f, "DS")
1613	return r, e, s
1614}
1615
1616func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1617	r, e, s := setDSs(h, c, o, f, "DLV")
1618	if r != nil {
1619		return &DLV{*r.(*DS)}, e, s
1620	}
1621	return nil, e, s
1622}
1623
1624func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1625	r, e, s := setDSs(h, c, o, f, "CDS")
1626	if r != nil {
1627		return &CDS{*r.(*DS)}, e, s
1628	}
1629	return nil, e, s
1630}
1631
1632func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1633	rr := new(TA)
1634	rr.Hdr = h
1635
1636	l := <-c
1637	if l.length == 0 { // dynamic update rr.
1638		return rr, nil, l.comment
1639	}
1640
1641	i, e := strconv.ParseUint(l.token, 10, 16)
1642	if e != nil || l.err {
1643		return nil, &ParseError{f, "bad TA KeyTag", l}, ""
1644	}
1645	rr.KeyTag = uint16(i)
1646	<-c // zBlank
1647	l = <-c
1648	if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
1649		i, ok := StringToAlgorithm[l.tokenUpper]
1650		if !ok || l.err {
1651			return nil, &ParseError{f, "bad TA Algorithm", l}, ""
1652		}
1653		rr.Algorithm = i
1654	} else {
1655		rr.Algorithm = uint8(i)
1656	}
1657	<-c // zBlank
1658	l = <-c
1659	i, e = strconv.ParseUint(l.token, 10, 8)
1660	if e != nil || l.err {
1661		return nil, &ParseError{f, "bad TA DigestType", l}, ""
1662	}
1663	rr.DigestType = uint8(i)
1664	s, e, c1 := endingToString(c, "bad TA Digest", f)
1665	if e != nil {
1666		return nil, e.(*ParseError), c1
1667	}
1668	rr.Digest = s
1669	return rr, nil, c1
1670}
1671
1672func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1673	rr := new(TLSA)
1674	rr.Hdr = h
1675
1676	l := <-c
1677	if l.length == 0 { // dynamic update rr.
1678		return rr, nil, l.comment
1679	}
1680
1681	i, e := strconv.ParseUint(l.token, 10, 8)
1682	if e != nil || l.err {
1683		return nil, &ParseError{f, "bad TLSA Usage", l}, ""
1684	}
1685	rr.Usage = uint8(i)
1686	<-c // zBlank
1687	l = <-c
1688	i, e = strconv.ParseUint(l.token, 10, 8)
1689	if e != nil || l.err {
1690		return nil, &ParseError{f, "bad TLSA Selector", l}, ""
1691	}
1692	rr.Selector = uint8(i)
1693	<-c // zBlank
1694	l = <-c
1695	i, e = strconv.ParseUint(l.token, 10, 8)
1696	if e != nil || l.err {
1697		return nil, &ParseError{f, "bad TLSA MatchingType", l}, ""
1698	}
1699	rr.MatchingType = uint8(i)
1700	// So this needs be e2 (i.e. different than e), because...??t
1701	s, e2, c1 := endingToString(c, "bad TLSA Certificate", f)
1702	if e2 != nil {
1703		return nil, e2, c1
1704	}
1705	rr.Certificate = s
1706	return rr, nil, c1
1707}
1708
1709func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1710	rr := new(SMIMEA)
1711	rr.Hdr = h
1712
1713	l := <-c
1714	if l.length == 0 { // dynamic update rr.
1715		return rr, nil, l.comment
1716	}
1717
1718	i, e := strconv.ParseUint(l.token, 10, 8)
1719	if e != nil || l.err {
1720		return nil, &ParseError{f, "bad SMIMEA Usage", l}, ""
1721	}
1722	rr.Usage = uint8(i)
1723	<-c // zBlank
1724	l = <-c
1725	i, e = strconv.ParseUint(l.token, 10, 8)
1726	if e != nil || l.err {
1727		return nil, &ParseError{f, "bad SMIMEA Selector", l}, ""
1728	}
1729	rr.Selector = uint8(i)
1730	<-c // zBlank
1731	l = <-c
1732	i, e = strconv.ParseUint(l.token, 10, 8)
1733	if e != nil || l.err {
1734		return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, ""
1735	}
1736	rr.MatchingType = uint8(i)
1737	// So this needs be e2 (i.e. different than e), because...??t
1738	s, e2, c1 := endingToString(c, "bad SMIMEA Certificate", f)
1739	if e2 != nil {
1740		return nil, e2, c1
1741	}
1742	rr.Certificate = s
1743	return rr, nil, c1
1744}
1745
1746func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1747	rr := new(RFC3597)
1748	rr.Hdr = h
1749
1750	l := <-c
1751	if l.token != "\\#" {
1752		return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
1753	}
1754
1755	<-c // zBlank
1756	l = <-c
1757	rdlength, e := strconv.Atoi(l.token)
1758	if e != nil || l.err {
1759		return nil, &ParseError{f, "bad RFC3597 Rdata ", l}, ""
1760	}
1761
1762	s, e1, c1 := endingToString(c, "bad RFC3597 Rdata", f)
1763	if e1 != nil {
1764		return nil, e1, c1
1765	}
1766	if rdlength*2 != len(s) {
1767		return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
1768	}
1769	rr.Rdata = s
1770	return rr, nil, c1
1771}
1772
1773func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1774	rr := new(SPF)
1775	rr.Hdr = h
1776
1777	s, e, c1 := endingToTxtSlice(c, "bad SPF Txt", f)
1778	if e != nil {
1779		return nil, e, ""
1780	}
1781	rr.Txt = s
1782	return rr, nil, c1
1783}
1784
1785func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1786	rr := new(AVC)
1787	rr.Hdr = h
1788
1789	s, e, c1 := endingToTxtSlice(c, "bad AVC Txt", f)
1790	if e != nil {
1791		return nil, e, ""
1792	}
1793	rr.Txt = s
1794	return rr, nil, c1
1795}
1796
1797func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1798	rr := new(TXT)
1799	rr.Hdr = h
1800
1801	// no zBlank reading here, because all this rdata is TXT
1802	s, e, c1 := endingToTxtSlice(c, "bad TXT Txt", f)
1803	if e != nil {
1804		return nil, e, ""
1805	}
1806	rr.Txt = s
1807	return rr, nil, c1
1808}
1809
1810// identical to setTXT
1811func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1812	rr := new(NINFO)
1813	rr.Hdr = h
1814
1815	s, e, c1 := endingToTxtSlice(c, "bad NINFO ZSData", f)
1816	if e != nil {
1817		return nil, e, ""
1818	}
1819	rr.ZSData = s
1820	return rr, nil, c1
1821}
1822
1823func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1824	rr := new(URI)
1825	rr.Hdr = h
1826
1827	l := <-c
1828	if l.length == 0 { // dynamic update rr.
1829		return rr, nil, ""
1830	}
1831
1832	i, e := strconv.ParseUint(l.token, 10, 16)
1833	if e != nil || l.err {
1834		return nil, &ParseError{f, "bad URI Priority", l}, ""
1835	}
1836	rr.Priority = uint16(i)
1837	<-c // zBlank
1838	l = <-c
1839	i, e = strconv.ParseUint(l.token, 10, 16)
1840	if e != nil || l.err {
1841		return nil, &ParseError{f, "bad URI Weight", l}, ""
1842	}
1843	rr.Weight = uint16(i)
1844
1845	<-c // zBlank
1846	s, err, c1 := endingToTxtSlice(c, "bad URI Target", f)
1847	if err != nil {
1848		return nil, err, ""
1849	}
1850	if len(s) != 1 {
1851		return nil, &ParseError{f, "bad URI Target", l}, ""
1852	}
1853	rr.Target = s[0]
1854	return rr, nil, c1
1855}
1856
1857func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1858	// awesome record to parse!
1859	rr := new(DHCID)
1860	rr.Hdr = h
1861
1862	s, e, c1 := endingToString(c, "bad DHCID Digest", f)
1863	if e != nil {
1864		return nil, e, c1
1865	}
1866	rr.Digest = s
1867	return rr, nil, c1
1868}
1869
1870func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1871	rr := new(NID)
1872	rr.Hdr = h
1873
1874	l := <-c
1875	if l.length == 0 { // dynamic update rr.
1876		return rr, nil, ""
1877	}
1878
1879	i, e := strconv.ParseUint(l.token, 10, 16)
1880	if e != nil || l.err {
1881		return nil, &ParseError{f, "bad NID Preference", l}, ""
1882	}
1883	rr.Preference = uint16(i)
1884	<-c     // zBlank
1885	l = <-c // zString
1886	u, err := stringToNodeID(l)
1887	if err != nil || l.err {
1888		return nil, err, ""
1889	}
1890	rr.NodeID = u
1891	return rr, nil, ""
1892}
1893
1894func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1895	rr := new(L32)
1896	rr.Hdr = h
1897
1898	l := <-c
1899	if l.length == 0 { // dynamic update rr.
1900		return rr, nil, ""
1901	}
1902
1903	i, e := strconv.ParseUint(l.token, 10, 16)
1904	if e != nil || l.err {
1905		return nil, &ParseError{f, "bad L32 Preference", l}, ""
1906	}
1907	rr.Preference = uint16(i)
1908	<-c     // zBlank
1909	l = <-c // zString
1910	rr.Locator32 = net.ParseIP(l.token)
1911	if rr.Locator32 == nil || l.err {
1912		return nil, &ParseError{f, "bad L32 Locator", l}, ""
1913	}
1914	return rr, nil, ""
1915}
1916
1917func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1918	rr := new(LP)
1919	rr.Hdr = h
1920
1921	l := <-c
1922	if l.length == 0 { // dynamic update rr.
1923		return rr, nil, ""
1924	}
1925
1926	i, e := strconv.ParseUint(l.token, 10, 16)
1927	if e != nil || l.err {
1928		return nil, &ParseError{f, "bad LP Preference", l}, ""
1929	}
1930	rr.Preference = uint16(i)
1931
1932	<-c     // zBlank
1933	l = <-c // zString
1934	rr.Fqdn = l.token
1935	name, nameOk := toAbsoluteName(l.token, o)
1936	if l.err || !nameOk {
1937		return nil, &ParseError{f, "bad LP Fqdn", l}, ""
1938	}
1939	rr.Fqdn = name
1940
1941	return rr, nil, ""
1942}
1943
1944func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1945	rr := new(L64)
1946	rr.Hdr = h
1947
1948	l := <-c
1949	if l.length == 0 { // dynamic update rr.
1950		return rr, nil, ""
1951	}
1952
1953	i, e := strconv.ParseUint(l.token, 10, 16)
1954	if e != nil || l.err {
1955		return nil, &ParseError{f, "bad L64 Preference", l}, ""
1956	}
1957	rr.Preference = uint16(i)
1958	<-c     // zBlank
1959	l = <-c // zString
1960	u, err := stringToNodeID(l)
1961	if err != nil || l.err {
1962		return nil, err, ""
1963	}
1964	rr.Locator64 = u
1965	return rr, nil, ""
1966}
1967
1968func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1969	rr := new(UID)
1970	rr.Hdr = h
1971
1972	l := <-c
1973	if l.length == 0 { // dynamic update rr.
1974		return rr, nil, ""
1975	}
1976
1977	i, e := strconv.ParseUint(l.token, 10, 32)
1978	if e != nil || l.err {
1979		return nil, &ParseError{f, "bad UID Uid", l}, ""
1980	}
1981	rr.Uid = uint32(i)
1982	return rr, nil, ""
1983}
1984
1985func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
1986	rr := new(GID)
1987	rr.Hdr = h
1988
1989	l := <-c
1990	if l.length == 0 { // dynamic update rr.
1991		return rr, nil, ""
1992	}
1993
1994	i, e := strconv.ParseUint(l.token, 10, 32)
1995	if e != nil || l.err {
1996		return nil, &ParseError{f, "bad GID Gid", l}, ""
1997	}
1998	rr.Gid = uint32(i)
1999	return rr, nil, ""
2000}
2001
2002func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
2003	rr := new(UINFO)
2004	rr.Hdr = h
2005
2006	s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
2007	if e != nil {
2008		return nil, e, c1
2009	}
2010	if ln := len(s); ln == 0 {
2011		return rr, nil, c1
2012	}
2013	rr.Uinfo = s[0] // silently discard anything after the first character-string
2014	return rr, nil, c1
2015}
2016
2017func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
2018	rr := new(PX)
2019	rr.Hdr = h
2020
2021	l := <-c
2022	if l.length == 0 { // dynamic update rr.
2023		return rr, nil, ""
2024	}
2025
2026	i, e := strconv.ParseUint(l.token, 10, 16)
2027	if e != nil || l.err {
2028		return nil, &ParseError{f, "bad PX Preference", l}, ""
2029	}
2030	rr.Preference = uint16(i)
2031
2032	<-c     // zBlank
2033	l = <-c // zString
2034	rr.Map822 = l.token
2035	map822, map822Ok := toAbsoluteName(l.token, o)
2036	if l.err || !map822Ok {
2037		return nil, &ParseError{f, "bad PX Map822", l}, ""
2038	}
2039	rr.Map822 = map822
2040
2041	<-c     // zBlank
2042	l = <-c // zString
2043	rr.Mapx400 = l.token
2044	mapx400, mapx400Ok := toAbsoluteName(l.token, o)
2045	if l.err || !mapx400Ok {
2046		return nil, &ParseError{f, "bad PX Mapx400", l}, ""
2047	}
2048	rr.Mapx400 = mapx400
2049
2050	return rr, nil, ""
2051}
2052
2053func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
2054	rr := new(CAA)
2055	rr.Hdr = h
2056
2057	l := <-c
2058	if l.length == 0 { // dynamic update rr.
2059		return rr, nil, l.comment
2060	}
2061
2062	i, err := strconv.ParseUint(l.token, 10, 8)
2063	if err != nil || l.err {
2064		return nil, &ParseError{f, "bad CAA Flag", l}, ""
2065	}
2066	rr.Flag = uint8(i)
2067
2068	<-c     // zBlank
2069	l = <-c // zString
2070	if l.value != zString {
2071		return nil, &ParseError{f, "bad CAA Tag", l}, ""
2072	}
2073	rr.Tag = l.token
2074
2075	<-c // zBlank
2076	s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f)
2077	if e != nil {
2078		return nil, e, ""
2079	}
2080	if len(s) != 1 {
2081		return nil, &ParseError{f, "bad CAA Value", l}, ""
2082	}
2083	rr.Value = s[0]
2084	return rr, nil, c1
2085}
2086
2087func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
2088	rr := new(TKEY)
2089	rr.Hdr = h
2090
2091	l := <-c
2092
2093	// Algorithm
2094	if l.value != zString {
2095		return nil, &ParseError{f, "bad TKEY algorithm", l}, ""
2096	}
2097	rr.Algorithm = l.token
2098	<-c // zBlank
2099
2100	// Get the key length and key values
2101	l = <-c
2102	i, err := strconv.ParseUint(l.token, 10, 8)
2103	if err != nil || l.err {
2104		return nil, &ParseError{f, "bad TKEY key length", l}, ""
2105	}
2106	rr.KeySize = uint16(i)
2107	<-c // zBlank
2108	l = <-c
2109	if l.value != zString {
2110		return nil, &ParseError{f, "bad TKEY key", l}, ""
2111	}
2112	rr.Key = l.token
2113	<-c // zBlank
2114
2115	// Get the otherdata length and string data
2116	l = <-c
2117	i, err = strconv.ParseUint(l.token, 10, 8)
2118	if err != nil || l.err {
2119		return nil, &ParseError{f, "bad TKEY otherdata length", l}, ""
2120	}
2121	rr.OtherLen = uint16(i)
2122	<-c // zBlank
2123	l = <-c
2124	if l.value != zString {
2125		return nil, &ParseError{f, "bad TKEY otherday", l}, ""
2126	}
2127	rr.OtherData = l.token
2128
2129	return rr, nil, ""
2130}
2131
2132var typeToparserFunc = map[uint16]parserFunc{
2133	TypeAAAA:       {setAAAA, false},
2134	TypeAFSDB:      {setAFSDB, false},
2135	TypeA:          {setA, false},
2136	TypeCAA:        {setCAA, true},
2137	TypeCDS:        {setCDS, true},
2138	TypeCDNSKEY:    {setCDNSKEY, true},
2139	TypeCERT:       {setCERT, true},
2140	TypeCNAME:      {setCNAME, false},
2141	TypeCSYNC:      {setCSYNC, true},
2142	TypeDHCID:      {setDHCID, true},
2143	TypeDLV:        {setDLV, true},
2144	TypeDNAME:      {setDNAME, false},
2145	TypeKEY:        {setKEY, true},
2146	TypeDNSKEY:     {setDNSKEY, true},
2147	TypeDS:         {setDS, true},
2148	TypeEID:        {setEID, true},
2149	TypeEUI48:      {setEUI48, false},
2150	TypeEUI64:      {setEUI64, false},
2151	TypeGID:        {setGID, false},
2152	TypeGPOS:       {setGPOS, false},
2153	TypeHINFO:      {setHINFO, true},
2154	TypeHIP:        {setHIP, true},
2155	TypeKX:         {setKX, false},
2156	TypeL32:        {setL32, false},
2157	TypeL64:        {setL64, false},
2158	TypeLOC:        {setLOC, true},
2159	TypeLP:         {setLP, false},
2160	TypeMB:         {setMB, false},
2161	TypeMD:         {setMD, false},
2162	TypeMF:         {setMF, false},
2163	TypeMG:         {setMG, false},
2164	TypeMINFO:      {setMINFO, false},
2165	TypeMR:         {setMR, false},
2166	TypeMX:         {setMX, false},
2167	TypeNAPTR:      {setNAPTR, false},
2168	TypeNID:        {setNID, false},
2169	TypeNIMLOC:     {setNIMLOC, true},
2170	TypeNINFO:      {setNINFO, true},
2171	TypeNSAPPTR:    {setNSAPPTR, false},
2172	TypeNSEC3PARAM: {setNSEC3PARAM, false},
2173	TypeNSEC3:      {setNSEC3, true},
2174	TypeNSEC:       {setNSEC, true},
2175	TypeNS:         {setNS, false},
2176	TypeOPENPGPKEY: {setOPENPGPKEY, true},
2177	TypePTR:        {setPTR, false},
2178	TypePX:         {setPX, false},
2179	TypeSIG:        {setSIG, true},
2180	TypeRKEY:       {setRKEY, true},
2181	TypeRP:         {setRP, false},
2182	TypeRRSIG:      {setRRSIG, true},
2183	TypeRT:         {setRT, false},
2184	TypeSMIMEA:     {setSMIMEA, true},
2185	TypeSOA:        {setSOA, false},
2186	TypeSPF:        {setSPF, true},
2187	TypeAVC:        {setAVC, true},
2188	TypeSRV:        {setSRV, false},
2189	TypeSSHFP:      {setSSHFP, true},
2190	TypeTALINK:     {setTALINK, false},
2191	TypeTA:         {setTA, true},
2192	TypeTLSA:       {setTLSA, true},
2193	TypeTXT:        {setTXT, true},
2194	TypeUID:        {setUID, false},
2195	TypeUINFO:      {setUINFO, true},
2196	TypeURI:        {setURI, true},
2197	TypeX25:        {setX25, false},
2198	TypeTKEY:       {setTKEY, true},
2199}
2200