1package dns
2
3import (
4	"fmt"
5	"net"
6	"strconv"
7	"strings"
8	"time"
9)
10
11type (
12	// Type is a DNS type.
13	Type uint16
14	// Class is a DNS class.
15	Class uint16
16	// Name is a DNS domain name.
17	Name string
18)
19
20// Packet formats
21
22// Wire constants and supported types.
23const (
24	// valid RR_Header.Rrtype and Question.qtype
25
26	TypeNone       uint16 = 0
27	TypeA          uint16 = 1
28	TypeNS         uint16 = 2
29	TypeMD         uint16 = 3
30	TypeMF         uint16 = 4
31	TypeCNAME      uint16 = 5
32	TypeSOA        uint16 = 6
33	TypeMB         uint16 = 7
34	TypeMG         uint16 = 8
35	TypeMR         uint16 = 9
36	TypeNULL       uint16 = 10
37	TypePTR        uint16 = 12
38	TypeHINFO      uint16 = 13
39	TypeMINFO      uint16 = 14
40	TypeMX         uint16 = 15
41	TypeTXT        uint16 = 16
42	TypeRP         uint16 = 17
43	TypeAFSDB      uint16 = 18
44	TypeX25        uint16 = 19
45	TypeISDN       uint16 = 20
46	TypeRT         uint16 = 21
47	TypeNSAPPTR    uint16 = 23
48	TypeSIG        uint16 = 24
49	TypeKEY        uint16 = 25
50	TypePX         uint16 = 26
51	TypeGPOS       uint16 = 27
52	TypeAAAA       uint16 = 28
53	TypeLOC        uint16 = 29
54	TypeNXT        uint16 = 30
55	TypeEID        uint16 = 31
56	TypeNIMLOC     uint16 = 32
57	TypeSRV        uint16 = 33
58	TypeATMA       uint16 = 34
59	TypeNAPTR      uint16 = 35
60	TypeKX         uint16 = 36
61	TypeCERT       uint16 = 37
62	TypeDNAME      uint16 = 39
63	TypeOPT        uint16 = 41 // EDNS
64	TypeDS         uint16 = 43
65	TypeSSHFP      uint16 = 44
66	TypeRRSIG      uint16 = 46
67	TypeNSEC       uint16 = 47
68	TypeDNSKEY     uint16 = 48
69	TypeDHCID      uint16 = 49
70	TypeNSEC3      uint16 = 50
71	TypeNSEC3PARAM uint16 = 51
72	TypeTLSA       uint16 = 52
73	TypeSMIMEA     uint16 = 53
74	TypeHIP        uint16 = 55
75	TypeNINFO      uint16 = 56
76	TypeRKEY       uint16 = 57
77	TypeTALINK     uint16 = 58
78	TypeCDS        uint16 = 59
79	TypeCDNSKEY    uint16 = 60
80	TypeOPENPGPKEY uint16 = 61
81	TypeCSYNC      uint16 = 62
82	TypeSPF        uint16 = 99
83	TypeUINFO      uint16 = 100
84	TypeUID        uint16 = 101
85	TypeGID        uint16 = 102
86	TypeUNSPEC     uint16 = 103
87	TypeNID        uint16 = 104
88	TypeL32        uint16 = 105
89	TypeL64        uint16 = 106
90	TypeLP         uint16 = 107
91	TypeEUI48      uint16 = 108
92	TypeEUI64      uint16 = 109
93	TypeURI        uint16 = 256
94	TypeCAA        uint16 = 257
95	TypeAVC        uint16 = 258
96
97	TypeTKEY uint16 = 249
98	TypeTSIG uint16 = 250
99
100	// valid Question.Qtype only
101	TypeIXFR  uint16 = 251
102	TypeAXFR  uint16 = 252
103	TypeMAILB uint16 = 253
104	TypeMAILA uint16 = 254
105	TypeANY   uint16 = 255
106
107	TypeTA       uint16 = 32768
108	TypeDLV      uint16 = 32769
109	TypeReserved uint16 = 65535
110
111	// valid Question.Qclass
112	ClassINET   = 1
113	ClassCSNET  = 2
114	ClassCHAOS  = 3
115	ClassHESIOD = 4
116	ClassNONE   = 254
117	ClassANY    = 255
118
119	// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
120	RcodeSuccess        = 0  // NoError   - No Error                          [DNS]
121	RcodeFormatError    = 1  // FormErr   - Format Error                      [DNS]
122	RcodeServerFailure  = 2  // ServFail  - Server Failure                    [DNS]
123	RcodeNameError      = 3  // NXDomain  - Non-Existent Domain               [DNS]
124	RcodeNotImplemented = 4  // NotImp    - Not Implemented                   [DNS]
125	RcodeRefused        = 5  // Refused   - Query Refused                     [DNS]
126	RcodeYXDomain       = 6  // YXDomain  - Name Exists when it should not    [DNS Update]
127	RcodeYXRrset        = 7  // YXRRSet   - RR Set Exists when it should not  [DNS Update]
128	RcodeNXRrset        = 8  // NXRRSet   - RR Set that should exist does not [DNS Update]
129	RcodeNotAuth        = 9  // NotAuth   - Server Not Authoritative for zone [DNS Update]
130	RcodeNotZone        = 10 // NotZone   - Name not contained in zone        [DNS Update/TSIG]
131	RcodeBadSig         = 16 // BADSIG    - TSIG Signature Failure            [TSIG]
132	RcodeBadVers        = 16 // BADVERS   - Bad OPT Version                   [EDNS0]
133	RcodeBadKey         = 17 // BADKEY    - Key not recognized                [TSIG]
134	RcodeBadTime        = 18 // BADTIME   - Signature out of time window      [TSIG]
135	RcodeBadMode        = 19 // BADMODE   - Bad TKEY Mode                     [TKEY]
136	RcodeBadName        = 20 // BADNAME   - Duplicate key name                [TKEY]
137	RcodeBadAlg         = 21 // BADALG    - Algorithm not supported           [TKEY]
138	RcodeBadTrunc       = 22 // BADTRUNC  - Bad Truncation                    [TSIG]
139	RcodeBadCookie      = 23 // BADCOOKIE - Bad/missing Server Cookie         [DNS Cookies]
140
141	// Message Opcodes. There is no 3.
142	OpcodeQuery  = 0
143	OpcodeIQuery = 1
144	OpcodeStatus = 2
145	OpcodeNotify = 4
146	OpcodeUpdate = 5
147)
148
149// Header is the wire format for the DNS packet header.
150type Header struct {
151	Id                                 uint16
152	Bits                               uint16
153	Qdcount, Ancount, Nscount, Arcount uint16
154}
155
156const (
157	headerSize = 12
158
159	// Header.Bits
160	_QR = 1 << 15 // query/response (response=1)
161	_AA = 1 << 10 // authoritative
162	_TC = 1 << 9  // truncated
163	_RD = 1 << 8  // recursion desired
164	_RA = 1 << 7  // recursion available
165	_Z  = 1 << 6  // Z
166	_AD = 1 << 5  // authticated data
167	_CD = 1 << 4  // checking disabled
168)
169
170// Various constants used in the LOC RR, See RFC 1887.
171const (
172	LOC_EQUATOR       = 1 << 31 // RFC 1876, Section 2.
173	LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
174	LOC_HOURS         = 60 * 1000
175	LOC_DEGREES       = 60 * LOC_HOURS
176	LOC_ALTITUDEBASE  = 100000
177)
178
179// Different Certificate Types, see RFC 4398, Section 2.1
180const (
181	CertPKIX = 1 + iota
182	CertSPKI
183	CertPGP
184	CertIPIX
185	CertISPKI
186	CertIPGP
187	CertACPKIX
188	CertIACPKIX
189	CertURI = 253
190	CertOID = 254
191)
192
193// CertTypeToString converts the Cert Type to its string representation.
194// See RFC 4398 and RFC 6944.
195var CertTypeToString = map[uint16]string{
196	CertPKIX:    "PKIX",
197	CertSPKI:    "SPKI",
198	CertPGP:     "PGP",
199	CertIPIX:    "IPIX",
200	CertISPKI:   "ISPKI",
201	CertIPGP:    "IPGP",
202	CertACPKIX:  "ACPKIX",
203	CertIACPKIX: "IACPKIX",
204	CertURI:     "URI",
205	CertOID:     "OID",
206}
207
208// StringToCertType is the reverseof CertTypeToString.
209var StringToCertType = reverseInt16(CertTypeToString)
210
211//go:generate go run types_generate.go
212
213// Question holds a DNS question. There can be multiple questions in the
214// question section of a message. Usually there is just one.
215type Question struct {
216	Name   string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
217	Qtype  uint16
218	Qclass uint16
219}
220
221func (q *Question) len() int {
222	return len(q.Name) + 1 + 2 + 2
223}
224
225func (q *Question) String() (s string) {
226	// prefix with ; (as in dig)
227	s = ";" + sprintName(q.Name) + "\t"
228	s += Class(q.Qclass).String() + "\t"
229	s += " " + Type(q.Qtype).String()
230	return s
231}
232
233// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY
234// is named "*" there.
235type ANY struct {
236	Hdr RR_Header
237	// Does not have any rdata
238}
239
240func (rr *ANY) String() string { return rr.Hdr.String() }
241
242// CNAME RR. See RFC 1034.
243type CNAME struct {
244	Hdr    RR_Header
245	Target string `dns:"cdomain-name"`
246}
247
248func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
249
250// HINFO RR. See RFC 1034.
251type HINFO struct {
252	Hdr RR_Header
253	Cpu string
254	Os  string
255}
256
257func (rr *HINFO) String() string {
258	return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
259}
260
261// MB RR. See RFC 1035.
262type MB struct {
263	Hdr RR_Header
264	Mb  string `dns:"cdomain-name"`
265}
266
267func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
268
269// MG RR. See RFC 1035.
270type MG struct {
271	Hdr RR_Header
272	Mg  string `dns:"cdomain-name"`
273}
274
275func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
276
277// MINFO RR. See RFC 1035.
278type MINFO struct {
279	Hdr   RR_Header
280	Rmail string `dns:"cdomain-name"`
281	Email string `dns:"cdomain-name"`
282}
283
284func (rr *MINFO) String() string {
285	return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
286}
287
288// MR RR. See RFC 1035.
289type MR struct {
290	Hdr RR_Header
291	Mr  string `dns:"cdomain-name"`
292}
293
294func (rr *MR) String() string {
295	return rr.Hdr.String() + sprintName(rr.Mr)
296}
297
298// MF RR. See RFC 1035.
299type MF struct {
300	Hdr RR_Header
301	Mf  string `dns:"cdomain-name"`
302}
303
304func (rr *MF) String() string {
305	return rr.Hdr.String() + sprintName(rr.Mf)
306}
307
308// MD RR. See RFC 1035.
309type MD struct {
310	Hdr RR_Header
311	Md  string `dns:"cdomain-name"`
312}
313
314func (rr *MD) String() string {
315	return rr.Hdr.String() + sprintName(rr.Md)
316}
317
318// MX RR. See RFC 1035.
319type MX struct {
320	Hdr        RR_Header
321	Preference uint16
322	Mx         string `dns:"cdomain-name"`
323}
324
325func (rr *MX) String() string {
326	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
327}
328
329// AFSDB RR. See RFC 1183.
330type AFSDB struct {
331	Hdr      RR_Header
332	Subtype  uint16
333	Hostname string `dns:"cdomain-name"`
334}
335
336func (rr *AFSDB) String() string {
337	return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
338}
339
340// X25 RR. See RFC 1183, Section 3.1.
341type X25 struct {
342	Hdr         RR_Header
343	PSDNAddress string
344}
345
346func (rr *X25) String() string {
347	return rr.Hdr.String() + rr.PSDNAddress
348}
349
350// RT RR. See RFC 1183, Section 3.3.
351type RT struct {
352	Hdr        RR_Header
353	Preference uint16
354	Host       string `dns:"cdomain-name"`
355}
356
357func (rr *RT) String() string {
358	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
359}
360
361// NS RR. See RFC 1035.
362type NS struct {
363	Hdr RR_Header
364	Ns  string `dns:"cdomain-name"`
365}
366
367func (rr *NS) String() string {
368	return rr.Hdr.String() + sprintName(rr.Ns)
369}
370
371// PTR RR. See RFC 1035.
372type PTR struct {
373	Hdr RR_Header
374	Ptr string `dns:"cdomain-name"`
375}
376
377func (rr *PTR) String() string {
378	return rr.Hdr.String() + sprintName(rr.Ptr)
379}
380
381// RP RR. See RFC 1138, Section 2.2.
382type RP struct {
383	Hdr  RR_Header
384	Mbox string `dns:"domain-name"`
385	Txt  string `dns:"domain-name"`
386}
387
388func (rr *RP) String() string {
389	return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
390}
391
392// SOA RR. See RFC 1035.
393type SOA struct {
394	Hdr     RR_Header
395	Ns      string `dns:"cdomain-name"`
396	Mbox    string `dns:"cdomain-name"`
397	Serial  uint32
398	Refresh uint32
399	Retry   uint32
400	Expire  uint32
401	Minttl  uint32
402}
403
404func (rr *SOA) String() string {
405	return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
406		" " + strconv.FormatInt(int64(rr.Serial), 10) +
407		" " + strconv.FormatInt(int64(rr.Refresh), 10) +
408		" " + strconv.FormatInt(int64(rr.Retry), 10) +
409		" " + strconv.FormatInt(int64(rr.Expire), 10) +
410		" " + strconv.FormatInt(int64(rr.Minttl), 10)
411}
412
413// TXT RR. See RFC 1035.
414type TXT struct {
415	Hdr RR_Header
416	Txt []string `dns:"txt"`
417}
418
419func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
420
421func sprintName(s string) string {
422	src := []byte(s)
423	dst := make([]byte, 0, len(src))
424	for i := 0; i < len(src); {
425		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
426			dst = append(dst, src[i:i+2]...)
427			i += 2
428		} else {
429			b, n := nextByte(src, i)
430			if n == 0 {
431				i++ // dangling back slash
432			} else if b == '.' {
433				dst = append(dst, b)
434			} else {
435				dst = appendDomainNameByte(dst, b)
436			}
437			i += n
438		}
439	}
440	return string(dst)
441}
442
443func sprintTxtOctet(s string) string {
444	src := []byte(s)
445	dst := make([]byte, 0, len(src))
446	dst = append(dst, '"')
447	for i := 0; i < len(src); {
448		if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
449			dst = append(dst, src[i:i+2]...)
450			i += 2
451		} else {
452			b, n := nextByte(src, i)
453			if n == 0 {
454				i++ // dangling back slash
455			} else if b == '.' {
456				dst = append(dst, b)
457			} else {
458				if b < ' ' || b > '~' {
459					dst = appendByte(dst, b)
460				} else {
461					dst = append(dst, b)
462				}
463			}
464			i += n
465		}
466	}
467	dst = append(dst, '"')
468	return string(dst)
469}
470
471func sprintTxt(txt []string) string {
472	var out []byte
473	for i, s := range txt {
474		if i > 0 {
475			out = append(out, ` "`...)
476		} else {
477			out = append(out, '"')
478		}
479		bs := []byte(s)
480		for j := 0; j < len(bs); {
481			b, n := nextByte(bs, j)
482			if n == 0 {
483				break
484			}
485			out = appendTXTStringByte(out, b)
486			j += n
487		}
488		out = append(out, '"')
489	}
490	return string(out)
491}
492
493func appendDomainNameByte(s []byte, b byte) []byte {
494	switch b {
495	case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
496		return append(s, '\\', b)
497	}
498	return appendTXTStringByte(s, b)
499}
500
501func appendTXTStringByte(s []byte, b byte) []byte {
502	switch b {
503	case '"', '\\':
504		return append(s, '\\', b)
505	}
506	if b < ' ' || b > '~' {
507		return appendByte(s, b)
508	}
509	return append(s, b)
510}
511
512func appendByte(s []byte, b byte) []byte {
513	var buf [3]byte
514	bufs := strconv.AppendInt(buf[:0], int64(b), 10)
515	s = append(s, '\\')
516	for i := 0; i < 3-len(bufs); i++ {
517		s = append(s, '0')
518	}
519	for _, r := range bufs {
520		s = append(s, r)
521	}
522	return s
523}
524
525func nextByte(b []byte, offset int) (byte, int) {
526	if offset >= len(b) {
527		return 0, 0
528	}
529	if b[offset] != '\\' {
530		// not an escape sequence
531		return b[offset], 1
532	}
533	switch len(b) - offset {
534	case 1: // dangling escape
535		return 0, 0
536	case 2, 3: // too short to be \ddd
537	default: // maybe \ddd
538		if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
539			return dddToByte(b[offset+1:]), 4
540		}
541	}
542	// not \ddd, just an RFC 1035 "quoted" character
543	return b[offset+1], 2
544}
545
546// SPF RR. See RFC 4408, Section 3.1.1.
547type SPF struct {
548	Hdr RR_Header
549	Txt []string `dns:"txt"`
550}
551
552func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
553
554// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
555type AVC struct {
556	Hdr RR_Header
557	Txt []string `dns:"txt"`
558}
559
560func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
561
562// SRV RR. See RFC 2782.
563type SRV struct {
564	Hdr      RR_Header
565	Priority uint16
566	Weight   uint16
567	Port     uint16
568	Target   string `dns:"domain-name"`
569}
570
571func (rr *SRV) String() string {
572	return rr.Hdr.String() +
573		strconv.Itoa(int(rr.Priority)) + " " +
574		strconv.Itoa(int(rr.Weight)) + " " +
575		strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
576}
577
578// NAPTR RR. See RFC 2915.
579type NAPTR struct {
580	Hdr         RR_Header
581	Order       uint16
582	Preference  uint16
583	Flags       string
584	Service     string
585	Regexp      string
586	Replacement string `dns:"domain-name"`
587}
588
589func (rr *NAPTR) String() string {
590	return rr.Hdr.String() +
591		strconv.Itoa(int(rr.Order)) + " " +
592		strconv.Itoa(int(rr.Preference)) + " " +
593		"\"" + rr.Flags + "\" " +
594		"\"" + rr.Service + "\" " +
595		"\"" + rr.Regexp + "\" " +
596		rr.Replacement
597}
598
599// CERT RR. See RFC 4398.
600type CERT struct {
601	Hdr         RR_Header
602	Type        uint16
603	KeyTag      uint16
604	Algorithm   uint8
605	Certificate string `dns:"base64"`
606}
607
608func (rr *CERT) String() string {
609	var (
610		ok                  bool
611		certtype, algorithm string
612	)
613	if certtype, ok = CertTypeToString[rr.Type]; !ok {
614		certtype = strconv.Itoa(int(rr.Type))
615	}
616	if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok {
617		algorithm = strconv.Itoa(int(rr.Algorithm))
618	}
619	return rr.Hdr.String() + certtype +
620		" " + strconv.Itoa(int(rr.KeyTag)) +
621		" " + algorithm +
622		" " + rr.Certificate
623}
624
625// DNAME RR. See RFC 2672.
626type DNAME struct {
627	Hdr    RR_Header
628	Target string `dns:"domain-name"`
629}
630
631func (rr *DNAME) String() string {
632	return rr.Hdr.String() + sprintName(rr.Target)
633}
634
635// A RR. See RFC 1035.
636type A struct {
637	Hdr RR_Header
638	A   net.IP `dns:"a"`
639}
640
641func (rr *A) String() string {
642	if rr.A == nil {
643		return rr.Hdr.String()
644	}
645	return rr.Hdr.String() + rr.A.String()
646}
647
648// AAAA RR. See RFC 3596.
649type AAAA struct {
650	Hdr  RR_Header
651	AAAA net.IP `dns:"aaaa"`
652}
653
654func (rr *AAAA) String() string {
655	if rr.AAAA == nil {
656		return rr.Hdr.String()
657	}
658	return rr.Hdr.String() + rr.AAAA.String()
659}
660
661// PX RR. See RFC 2163.
662type PX struct {
663	Hdr        RR_Header
664	Preference uint16
665	Map822     string `dns:"domain-name"`
666	Mapx400    string `dns:"domain-name"`
667}
668
669func (rr *PX) String() string {
670	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
671}
672
673// GPOS RR. See RFC 1712.
674type GPOS struct {
675	Hdr       RR_Header
676	Longitude string
677	Latitude  string
678	Altitude  string
679}
680
681func (rr *GPOS) String() string {
682	return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
683}
684
685// LOC RR. See RFC RFC 1876.
686type LOC struct {
687	Hdr       RR_Header
688	Version   uint8
689	Size      uint8
690	HorizPre  uint8
691	VertPre   uint8
692	Latitude  uint32
693	Longitude uint32
694	Altitude  uint32
695}
696
697// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent
698// format and returns a string in m (two decimals for the cm)
699func cmToM(m, e uint8) string {
700	if e < 2 {
701		if e == 1 {
702			m *= 10
703		}
704
705		return fmt.Sprintf("0.%02d", m)
706	}
707
708	s := fmt.Sprintf("%d", m)
709	for e > 2 {
710		s += "0"
711		e--
712	}
713	return s
714}
715
716func (rr *LOC) String() string {
717	s := rr.Hdr.String()
718
719	lat := rr.Latitude
720	ns := "N"
721	if lat > LOC_EQUATOR {
722		lat = lat - LOC_EQUATOR
723	} else {
724		ns = "S"
725		lat = LOC_EQUATOR - lat
726	}
727	h := lat / LOC_DEGREES
728	lat = lat % LOC_DEGREES
729	m := lat / LOC_HOURS
730	lat = lat % LOC_HOURS
731	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
732
733	lon := rr.Longitude
734	ew := "E"
735	if lon > LOC_PRIMEMERIDIAN {
736		lon = lon - LOC_PRIMEMERIDIAN
737	} else {
738		ew = "W"
739		lon = LOC_PRIMEMERIDIAN - lon
740	}
741	h = lon / LOC_DEGREES
742	lon = lon % LOC_DEGREES
743	m = lon / LOC_HOURS
744	lon = lon % LOC_HOURS
745	s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
746
747	var alt = float64(rr.Altitude) / 100
748	alt -= LOC_ALTITUDEBASE
749	if rr.Altitude%100 != 0 {
750		s += fmt.Sprintf("%.2fm ", alt)
751	} else {
752		s += fmt.Sprintf("%.0fm ", alt)
753	}
754
755	s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
756	s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
757	s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
758
759	return s
760}
761
762// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
763type SIG struct {
764	RRSIG
765}
766
767// RRSIG RR. See RFC 4034 and RFC 3755.
768type RRSIG struct {
769	Hdr         RR_Header
770	TypeCovered uint16
771	Algorithm   uint8
772	Labels      uint8
773	OrigTtl     uint32
774	Expiration  uint32
775	Inception   uint32
776	KeyTag      uint16
777	SignerName  string `dns:"domain-name"`
778	Signature   string `dns:"base64"`
779}
780
781func (rr *RRSIG) String() string {
782	s := rr.Hdr.String()
783	s += Type(rr.TypeCovered).String()
784	s += " " + strconv.Itoa(int(rr.Algorithm)) +
785		" " + strconv.Itoa(int(rr.Labels)) +
786		" " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
787		" " + TimeToString(rr.Expiration) +
788		" " + TimeToString(rr.Inception) +
789		" " + strconv.Itoa(int(rr.KeyTag)) +
790		" " + sprintName(rr.SignerName) +
791		" " + rr.Signature
792	return s
793}
794
795// NSEC RR. See RFC 4034 and RFC 3755.
796type NSEC struct {
797	Hdr        RR_Header
798	NextDomain string   `dns:"domain-name"`
799	TypeBitMap []uint16 `dns:"nsec"`
800}
801
802func (rr *NSEC) String() string {
803	s := rr.Hdr.String() + sprintName(rr.NextDomain)
804	for i := 0; i < len(rr.TypeBitMap); i++ {
805		s += " " + Type(rr.TypeBitMap[i]).String()
806	}
807	return s
808}
809
810func (rr *NSEC) len() int {
811	l := rr.Hdr.len() + len(rr.NextDomain) + 1
812	lastwindow := uint32(2 ^ 32 + 1)
813	for _, t := range rr.TypeBitMap {
814		window := t / 256
815		if uint32(window) != lastwindow {
816			l += 1 + 32
817		}
818		lastwindow = uint32(window)
819	}
820	return l
821}
822
823// DLV RR. See RFC 4431.
824type DLV struct{ DS }
825
826// CDS RR. See RFC 7344.
827type CDS struct{ DS }
828
829// DS RR. See RFC 4034 and RFC 3658.
830type DS struct {
831	Hdr        RR_Header
832	KeyTag     uint16
833	Algorithm  uint8
834	DigestType uint8
835	Digest     string `dns:"hex"`
836}
837
838func (rr *DS) String() string {
839	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
840		" " + strconv.Itoa(int(rr.Algorithm)) +
841		" " + strconv.Itoa(int(rr.DigestType)) +
842		" " + strings.ToUpper(rr.Digest)
843}
844
845// KX RR. See RFC 2230.
846type KX struct {
847	Hdr        RR_Header
848	Preference uint16
849	Exchanger  string `dns:"domain-name"`
850}
851
852func (rr *KX) String() string {
853	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
854		" " + sprintName(rr.Exchanger)
855}
856
857// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
858type TA struct {
859	Hdr        RR_Header
860	KeyTag     uint16
861	Algorithm  uint8
862	DigestType uint8
863	Digest     string `dns:"hex"`
864}
865
866func (rr *TA) String() string {
867	return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
868		" " + strconv.Itoa(int(rr.Algorithm)) +
869		" " + strconv.Itoa(int(rr.DigestType)) +
870		" " + strings.ToUpper(rr.Digest)
871}
872
873// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
874type TALINK struct {
875	Hdr          RR_Header
876	PreviousName string `dns:"domain-name"`
877	NextName     string `dns:"domain-name"`
878}
879
880func (rr *TALINK) String() string {
881	return rr.Hdr.String() +
882		sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
883}
884
885// SSHFP RR. See RFC RFC 4255.
886type SSHFP struct {
887	Hdr         RR_Header
888	Algorithm   uint8
889	Type        uint8
890	FingerPrint string `dns:"hex"`
891}
892
893func (rr *SSHFP) String() string {
894	return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
895		" " + strconv.Itoa(int(rr.Type)) +
896		" " + strings.ToUpper(rr.FingerPrint)
897}
898
899// KEY RR. See RFC RFC 2535.
900type KEY struct {
901	DNSKEY
902}
903
904// CDNSKEY RR. See RFC 7344.
905type CDNSKEY struct {
906	DNSKEY
907}
908
909// DNSKEY RR. See RFC 4034 and RFC 3755.
910type DNSKEY struct {
911	Hdr       RR_Header
912	Flags     uint16
913	Protocol  uint8
914	Algorithm uint8
915	PublicKey string `dns:"base64"`
916}
917
918func (rr *DNSKEY) String() string {
919	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
920		" " + strconv.Itoa(int(rr.Protocol)) +
921		" " + strconv.Itoa(int(rr.Algorithm)) +
922		" " + rr.PublicKey
923}
924
925// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
926type RKEY struct {
927	Hdr       RR_Header
928	Flags     uint16
929	Protocol  uint8
930	Algorithm uint8
931	PublicKey string `dns:"base64"`
932}
933
934func (rr *RKEY) String() string {
935	return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
936		" " + strconv.Itoa(int(rr.Protocol)) +
937		" " + strconv.Itoa(int(rr.Algorithm)) +
938		" " + rr.PublicKey
939}
940
941// NSAPPTR RR. See RFC 1348.
942type NSAPPTR struct {
943	Hdr RR_Header
944	Ptr string `dns:"domain-name"`
945}
946
947func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
948
949// NSEC3 RR. See RFC 5155.
950type NSEC3 struct {
951	Hdr        RR_Header
952	Hash       uint8
953	Flags      uint8
954	Iterations uint16
955	SaltLength uint8
956	Salt       string `dns:"size-hex:SaltLength"`
957	HashLength uint8
958	NextDomain string   `dns:"size-base32:HashLength"`
959	TypeBitMap []uint16 `dns:"nsec"`
960}
961
962func (rr *NSEC3) String() string {
963	s := rr.Hdr.String()
964	s += strconv.Itoa(int(rr.Hash)) +
965		" " + strconv.Itoa(int(rr.Flags)) +
966		" " + strconv.Itoa(int(rr.Iterations)) +
967		" " + saltToString(rr.Salt) +
968		" " + rr.NextDomain
969	for i := 0; i < len(rr.TypeBitMap); i++ {
970		s += " " + Type(rr.TypeBitMap[i]).String()
971	}
972	return s
973}
974
975func (rr *NSEC3) len() int {
976	l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
977	lastwindow := uint32(2 ^ 32 + 1)
978	for _, t := range rr.TypeBitMap {
979		window := t / 256
980		if uint32(window) != lastwindow {
981			l += 1 + 32
982		}
983		lastwindow = uint32(window)
984	}
985	return l
986}
987
988// NSEC3PARAM RR. See RFC 5155.
989type NSEC3PARAM struct {
990	Hdr        RR_Header
991	Hash       uint8
992	Flags      uint8
993	Iterations uint16
994	SaltLength uint8
995	Salt       string `dns:"size-hex:SaltLength"`
996}
997
998func (rr *NSEC3PARAM) String() string {
999	s := rr.Hdr.String()
1000	s += strconv.Itoa(int(rr.Hash)) +
1001		" " + strconv.Itoa(int(rr.Flags)) +
1002		" " + strconv.Itoa(int(rr.Iterations)) +
1003		" " + saltToString(rr.Salt)
1004	return s
1005}
1006
1007// TKEY RR. See RFC 2930.
1008type TKEY struct {
1009	Hdr        RR_Header
1010	Algorithm  string `dns:"domain-name"`
1011	Inception  uint32
1012	Expiration uint32
1013	Mode       uint16
1014	Error      uint16
1015	KeySize    uint16
1016	Key        string `dns:"size-hex:KeySize"`
1017	OtherLen   uint16
1018	OtherData  string `dns:"size-hex:OtherLen"`
1019}
1020
1021// TKEY has no official presentation format, but this will suffice.
1022func (rr *TKEY) String() string {
1023	s := "\n;; TKEY PSEUDOSECTION:\n"
1024	s += rr.Hdr.String() + " " + rr.Algorithm + " " +
1025		strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
1026		strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
1027	return s
1028}
1029
1030// RFC3597 represents an unknown/generic RR. See RFC 3597.
1031type RFC3597 struct {
1032	Hdr   RR_Header
1033	Rdata string `dns:"hex"`
1034}
1035
1036func (rr *RFC3597) String() string {
1037	// Let's call it a hack
1038	s := rfc3597Header(rr.Hdr)
1039
1040	s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
1041	return s
1042}
1043
1044func rfc3597Header(h RR_Header) string {
1045	var s string
1046
1047	s += sprintName(h.Name) + "\t"
1048	s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
1049	s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t"
1050	s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t"
1051	return s
1052}
1053
1054// URI RR. See RFC 7553.
1055type URI struct {
1056	Hdr      RR_Header
1057	Priority uint16
1058	Weight   uint16
1059	Target   string `dns:"octet"`
1060}
1061
1062func (rr *URI) String() string {
1063	return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
1064		" " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
1065}
1066
1067// DHCID RR. See RFC 4701.
1068type DHCID struct {
1069	Hdr    RR_Header
1070	Digest string `dns:"base64"`
1071}
1072
1073func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
1074
1075// TLSA RR. See RFC 6698.
1076type TLSA struct {
1077	Hdr          RR_Header
1078	Usage        uint8
1079	Selector     uint8
1080	MatchingType uint8
1081	Certificate  string `dns:"hex"`
1082}
1083
1084func (rr *TLSA) String() string {
1085	return rr.Hdr.String() +
1086		strconv.Itoa(int(rr.Usage)) +
1087		" " + strconv.Itoa(int(rr.Selector)) +
1088		" " + strconv.Itoa(int(rr.MatchingType)) +
1089		" " + rr.Certificate
1090}
1091
1092// SMIMEA RR. See RFC 8162.
1093type SMIMEA struct {
1094	Hdr          RR_Header
1095	Usage        uint8
1096	Selector     uint8
1097	MatchingType uint8
1098	Certificate  string `dns:"hex"`
1099}
1100
1101func (rr *SMIMEA) String() string {
1102	s := rr.Hdr.String() +
1103		strconv.Itoa(int(rr.Usage)) +
1104		" " + strconv.Itoa(int(rr.Selector)) +
1105		" " + strconv.Itoa(int(rr.MatchingType))
1106
1107	// Every Nth char needs a space on this output. If we output
1108	// this as one giant line, we can't read it can in because in some cases
1109	// the cert length overflows scan.maxTok (2048).
1110	sx := splitN(rr.Certificate, 1024) // conservative value here
1111	s += " " + strings.Join(sx, " ")
1112	return s
1113}
1114
1115// HIP RR. See RFC 8005.
1116type HIP struct {
1117	Hdr                RR_Header
1118	HitLength          uint8
1119	PublicKeyAlgorithm uint8
1120	PublicKeyLength    uint16
1121	Hit                string   `dns:"size-hex:HitLength"`
1122	PublicKey          string   `dns:"size-base64:PublicKeyLength"`
1123	RendezvousServers  []string `dns:"domain-name"`
1124}
1125
1126func (rr *HIP) String() string {
1127	s := rr.Hdr.String() +
1128		strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
1129		" " + rr.Hit +
1130		" " + rr.PublicKey
1131	for _, d := range rr.RendezvousServers {
1132		s += " " + sprintName(d)
1133	}
1134	return s
1135}
1136
1137// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
1138type NINFO struct {
1139	Hdr    RR_Header
1140	ZSData []string `dns:"txt"`
1141}
1142
1143func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
1144
1145// NID RR. See RFC RFC 6742.
1146type NID struct {
1147	Hdr        RR_Header
1148	Preference uint16
1149	NodeID     uint64
1150}
1151
1152func (rr *NID) String() string {
1153	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
1154	node := fmt.Sprintf("%0.16x", rr.NodeID)
1155	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
1156	return s
1157}
1158
1159// L32 RR, See RFC 6742.
1160type L32 struct {
1161	Hdr        RR_Header
1162	Preference uint16
1163	Locator32  net.IP `dns:"a"`
1164}
1165
1166func (rr *L32) String() string {
1167	if rr.Locator32 == nil {
1168		return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
1169	}
1170	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
1171		" " + rr.Locator32.String()
1172}
1173
1174// L64 RR, See RFC 6742.
1175type L64 struct {
1176	Hdr        RR_Header
1177	Preference uint16
1178	Locator64  uint64
1179}
1180
1181func (rr *L64) String() string {
1182	s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
1183	node := fmt.Sprintf("%0.16X", rr.Locator64)
1184	s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
1185	return s
1186}
1187
1188// LP RR. See RFC 6742.
1189type LP struct {
1190	Hdr        RR_Header
1191	Preference uint16
1192	Fqdn       string `dns:"domain-name"`
1193}
1194
1195func (rr *LP) String() string {
1196	return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
1197}
1198
1199// EUI48 RR. See RFC 7043.
1200type EUI48 struct {
1201	Hdr     RR_Header
1202	Address uint64 `dns:"uint48"`
1203}
1204
1205func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
1206
1207// EUI64 RR. See RFC 7043.
1208type EUI64 struct {
1209	Hdr     RR_Header
1210	Address uint64
1211}
1212
1213func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
1214
1215// CAA RR. See RFC 6844.
1216type CAA struct {
1217	Hdr   RR_Header
1218	Flag  uint8
1219	Tag   string
1220	Value string `dns:"octet"`
1221}
1222
1223func (rr *CAA) String() string {
1224	return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
1225}
1226
1227// UID RR. Deprecated, IANA-Reserved.
1228type UID struct {
1229	Hdr RR_Header
1230	Uid uint32
1231}
1232
1233func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
1234
1235// GID RR. Deprecated, IANA-Reserved.
1236type GID struct {
1237	Hdr RR_Header
1238	Gid uint32
1239}
1240
1241func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
1242
1243// UINFO RR. Deprecated, IANA-Reserved.
1244type UINFO struct {
1245	Hdr   RR_Header
1246	Uinfo string
1247}
1248
1249func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
1250
1251// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
1252type EID struct {
1253	Hdr      RR_Header
1254	Endpoint string `dns:"hex"`
1255}
1256
1257func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
1258
1259// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
1260type NIMLOC struct {
1261	Hdr     RR_Header
1262	Locator string `dns:"hex"`
1263}
1264
1265func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
1266
1267// OPENPGPKEY RR. See RFC 7929.
1268type OPENPGPKEY struct {
1269	Hdr       RR_Header
1270	PublicKey string `dns:"base64"`
1271}
1272
1273func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
1274
1275// CSYNC RR. See RFC 7477.
1276type CSYNC struct {
1277	Hdr        RR_Header
1278	Serial     uint32
1279	Flags      uint16
1280	TypeBitMap []uint16 `dns:"nsec"`
1281}
1282
1283func (rr *CSYNC) String() string {
1284	s := rr.Hdr.String() + strconv.FormatInt(int64(rr.Serial), 10) + " " + strconv.Itoa(int(rr.Flags))
1285
1286	for i := 0; i < len(rr.TypeBitMap); i++ {
1287		s += " " + Type(rr.TypeBitMap[i]).String()
1288	}
1289	return s
1290}
1291
1292func (rr *CSYNC) len() int {
1293	l := rr.Hdr.len() + 4 + 2
1294	lastwindow := uint32(2 ^ 32 + 1)
1295	for _, t := range rr.TypeBitMap {
1296		window := t / 256
1297		if uint32(window) != lastwindow {
1298			l += 1 + 32
1299		}
1300		lastwindow = uint32(window)
1301	}
1302	return l
1303}
1304
1305// TimeToString translates the RRSIG's incep. and expir. times to the
1306// string representation used when printing the record.
1307// It takes serial arithmetic (RFC 1982) into account.
1308func TimeToString(t uint32) string {
1309	mod := ((int64(t) - time.Now().Unix()) / year68) - 1
1310	if mod < 0 {
1311		mod = 0
1312	}
1313	ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
1314	return ti.Format("20060102150405")
1315}
1316
1317// StringToTime translates the RRSIG's incep. and expir. times from
1318// string values like "20110403154150" to an 32 bit integer.
1319// It takes serial arithmetic (RFC 1982) into account.
1320func StringToTime(s string) (uint32, error) {
1321	t, err := time.Parse("20060102150405", s)
1322	if err != nil {
1323		return 0, err
1324	}
1325	mod := (t.Unix() / year68) - 1
1326	if mod < 0 {
1327		mod = 0
1328	}
1329	return uint32(t.Unix() - (mod * year68)), nil
1330}
1331
1332// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
1333func saltToString(s string) string {
1334	if len(s) == 0 {
1335		return "-"
1336	}
1337	return strings.ToUpper(s)
1338}
1339
1340func euiToString(eui uint64, bits int) (hex string) {
1341	switch bits {
1342	case 64:
1343		hex = fmt.Sprintf("%16.16x", eui)
1344		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
1345			"-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16]
1346	case 48:
1347		hex = fmt.Sprintf("%12.12x", eui)
1348		hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
1349			"-" + hex[8:10] + "-" + hex[10:12]
1350	}
1351	return
1352}
1353
1354// copyIP returns a copy of ip.
1355func copyIP(ip net.IP) net.IP {
1356	p := make(net.IP, len(ip))
1357	copy(p, ip)
1358	return p
1359}
1360
1361// SplitN splits a string into N sized string chunks.
1362// This might become an exported function once.
1363func splitN(s string, n int) []string {
1364	if len(s) < n {
1365		return []string{s}
1366	}
1367	sx := []string{}
1368	p, i := 0, n
1369	for {
1370		if i <= len(s) {
1371			sx = append(sx, s[p:i])
1372		} else {
1373			sx = append(sx, s[p:])
1374			break
1375
1376		}
1377		p, i = p+n, i+n
1378	}
1379
1380	return sx
1381}
1382