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