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